1. 程式人生 > >RecyclerView.Adapter notifyDataSetChanged 不起作用

RecyclerView.Adapter notifyDataSetChanged 不起作用

最近專案裡要添加個聊天功能,我們使用的是環信SDK。

如果應用啟動,不在聊天介面,接收到訊息後就彈出通知欄訊息通知使用者,點選進入聊天介面。

如果使用者已經在聊天介面,就要將接收到的資料新增到adapter裡,動態顯示訊息。

問題卡在,接收到訊息後呼叫更新介面回撥,給adapter裡add新資料,然後呼叫adapter.notifyDataSetChanged()。

結果資料並沒有重新整理!

檢視log,呼叫notifyDataSetChanged()後,onCreateViewHolder、onBindViewHolder方法並沒有執行。

找了很久,最後在StackOverFlow上找到了答案,

原文在這裡

原來在我後臺接收到資料呼叫更新介面回撥方法時,其實和當前Activity不在同一個執行緒,我忙傻了把這點給忘了。

在回撥裡應該通過Handler傳送資料到主執行緒,然後再給adapter裡填資料,呼叫notifyDataSetChanged();

執行緒回撥方法裡:

 Message handleMsg = new Message();
        Bundle bundle = new Bundle();
        bundle.putParcelable("1",message);
        handleMsg.setData(bundle);
        handleMsg.what
= 1; updateChatHandler.sendMessage(handleMsg);

處理訊息的Handler:

Handler updateChatHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what){
                case 1:
                    EMMessage message = msg.getData().getParcelable("1"
); // UIUtils.showToastSafe(WaitForChatActivity.this, "接收到訊息的回撥" + message.getBody()); setChatDataFromNet(message); if (adapter != null) { addData2Adapter(receiveMsg, false); } break; } super.handleMessage(msg); } };

總結

更新資料時在主執行緒填資料,然後再呼叫RecyclerView.Adapter的 notifyDataSetChanged方法。

Android 開發過程中經常遇到更新介面沒反應的情況,一開始我總是覺得自己程式碼這麼完美!一定是資料或者編譯器問題,結果一次次被打臉。T。T

今天總結下開發過程中遇到的幾種更新 UI 沒反應原因:

  1. 資料為空

有時候服務端返回資料有誤或者自己傳遞的資料為空,可以打個 Log 或者 跟個斷點看看。

  1. 在子執行緒更新 UI

有時候在 請求介面回撥、ListView 或者 RecyclerView 的 Adapter 裡需要進行一些 UI 更新,這時不起作用的原因大多是因為我們在 子執行緒中更新UI。

子執行緒更新 UI 的方法有好多種,最終目的都是把訊息發到主執行緒去操作:

寫個 Handler 裡進行 UI 操作,子執行緒 傳送訊息
在runOnUiThread中

Activity.runOnUiThread(new Runnable() {
        @Override
        public void run() {
            //do the ui-job
        }
    });

或者 post 到主執行緒

myView.post(new Runnable() {
            @Override
            public void run() {
                //do the ui-job
            }
        })

3.方法呼叫錯誤

最常見的就是修改 ImageVIew 圖片,應該呼叫

setImageResource
或者其他 setImageXXX 方法

而不是

setBackground
等 setBackgroundXXX 方法,後者只是修改背景,而不是圖片本身。