關於ListView中adapter呼叫notifyDataSetChanged失效的原因總結
阿新 • • 發佈:2019-01-29
一、前言
相信很多人都曾經被這個問題困擾,當然我也是這樣過來的,原來以為只要資料變了,呼叫adapter的notifyDataSetChanged就會更新列表,然而結果卻沒有實現,其實是在一些細節上沒有注意造成的,所以現在對這個問題進行下總結希望可以幫助到有需要的人。
二、原因分析
有以下三個原因:1、資料來源沒有更新,呼叫notifyDataSetChanged無效。
2、資料來源更新了,但是它指向新的引用,呼叫notifyDataSetChanged無效。
3、資料來源更新了,但是adpter沒有收到訊息通知,無法動態更新列表。
一般來說,我們都是第二個原因造成的。
三、舉例分析
分析了原因還是直接寫個例子來說明,這樣更加清楚。 正常情況:點選新增,然後點選更新介面。事件程式碼:
myAdapter = new MyAdapter(this, peopleList)public void onClicked(View view) { switch (view.getId()) { case R.id.btn_add://新增 for (int i = 0; i < 2; i++) { People people = new People("女神" + i, imgs[2]); peopleList.add(people); } break; case R.id.btn_add2://新增失敗 peopleList = new ArrayList<>(); for (int i = 0; i < 2; i++) { People people = new People("女神" + i, imgs[3]); peopleList.add(people); } // myAdapter = new MyAdapter(this, peopleList); break; case R.id.btn_replace://通知更新 peopleList = new ArrayList<>(); for (int i = 0; i < 2; i++) { People people = new People("女神" + i, imgs[4]); peopleList.add(people); } myAdapter.setData(peopleList); break; case R.id.btn_notify://更新 myAdapter.notifyDataSetChanged(); break; default: break; } }
例項化MyAdapter,這裡兩個引數。點選新增後資料來源peopleList添加了兩個People物件,點選更新,實際就是呼叫notifyDataSetChanged(),listview正常更新,ok沒有問題! 接著演示個失敗的案例。
我已經拼命點了怎麼就是沒有效果,對比上面的程式碼,發現點選失敗的case裡多了一句話, peopleList = new ArrayList<>(); 難道就是這句造成的?沒錯,就是它,也就是上面的原因2。雖然資料來源更新了,但是它指向新的引用,可是我們的Adapter繫結的還是原來資料來源的引用,自然你呼叫更新,我們的Adapter認為是沒有變化,所以失效。沒事我們重新繫結下Adapter的資料來源,開啟上面註釋的話,再來,可是結果你會發現這樣也是不行的,因為雖然Adaper是更新了資料來源,可是這個Adapter和原來的Adapter已經不一樣了,listView卻還是不知道這樣的變化,所以呼叫也會無效。
public void setData(List<People> newPeopleList){
this.peopleList = newPeopleList;
}
四、總結
上面說的這麼多,不知道大家有沒有懂,其實根本原因就是listview+adapter+資料來源這三者的繫結,如果因為指向新的引用造成三者沒有了原來的捆綁關係,自然呼叫notifyDataSetChanged()就會失效。
原始碼下載