【Android开发小记】RecycleView数据无法更新问题

876 阅读3分钟

问题提出

近期在写一个项目时遇到一个这样的问题:通过post请求向服务器请求一段文字信息,得到包含信息的json数据后使用JsonObject()对其进行解析,也获取到信息的值,但在recycleView中始终不能自动显示,必须手动滑动recycleView才能将信息显示在界面上。
代码如下

 CommitResult= HttpUtil.post(talkUrl, token, "application/json", params); 
 JSONObject object=new JSONObject(CommitResult);
 String result1=object.getJSONObject("result").getJSONObject("response").getJSONArray("name").get(0).toString();
 JSONObject object1=new JSONObject(result1);
 message1=object1.getString("message");
 tb_Content = new Tb_Content(message1, 0);
 tbContentList.add(tb_Content);
 recyclerViewAdapter.notifyDataSetChanged();

问题分析

首先是先排除获取数据的问题,数据是能够获取到并在我手动滑动recycleView后显示出来的,所以很可能是我recycleViewAdapternotifyDataSetChanged()调用方式出现了问题。
在此处我先通过HttpUtil类中的post方式对我想要发送给服务器的数据进行封装发送并将返回的值赋给CommitResult这个变量,会不会是此时的等待请求网页结果返回结果时notifyDataSetChanged()已经执行了呢?

尝试方式

此处想到的是为了避免变量接受返回结果时造成的等待,所以便新开了一个handler作为接受到数据后再回到主线程进行页面更新的一个方法。代码如下:

Handler handler;
...
 CommitResult= HttpUtil.post(talkUrl, token, "application/json", params); 
 JSONObject object=new JSONObject(CommitResult);
 String result1=object.getJSONObject("result").getJSONObject("response").getJSONArray("name").get(0).toString();
 JSONObject object1=new JSONObject(result1);
 message1=object1.getString("message");
 Message m = new Message();
 m.obj=robotSay;
handler.sendMessage(m);
...
@Override
    protected void onResume() {
        super.onResume();
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                tb_chatContent = new Tb_ChatContent(msg.obj.toString(), 0);
                tbChatContentList.add(tb_chatContent);
                recyclerViewAdapter.notifyDataSetChanged();
            }
        };

重新run一次程序后发现已经可以自动更新而不用再手动滑动屏幕更新了。

问题总结

事后想了想又仔细检查了下代码,发现实际上是一个很简单的问题。Android中规定了不能在子线程中来操作UI更新,在代码中调用的HttpUtil实际上是别人封装好的一个用于HTTP请求的类,请求http都是在子线程进行请求很少有程序会在主线程强制请求网络,所以实际上在那之后的操作都是在子线程中进行的,自然不能实现UI的更新,而引入Handler机制,在完成对网络部分的请求后,通过Message对象封装好接受到的消息并发送给出去,这条消息会被添加到MessageQueue的队列中等待被处理,而Looper(可以理解成消息队列的管理者)则会一直尝试从MessageQueue中取出待处理消息,最后分发回Handler的handleMessage()方法中。由于handler是在主线程被创建的,所以在接受到我们所发送的message过后,便可以在主线程中根据message的内容实现界面的更新等操作。
至此,问题解决,如果文章中有什么写的不妥之处,恳请大佬们批评指正。