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 沒反應原因:
- 資料為空
有時候服務端返回資料有誤或者自己傳遞的資料為空,可以打個 Log 或者 跟個斷點看看。
- 在子執行緒更新 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 方法,後者只是修改背景,而不是圖片本身。