1. 程式人生 > >關於ListView中adapter呼叫notifyDataSetChanged失效的原因總結

關於ListView中adapter呼叫notifyDataSetChanged失效的原因總結

一、前言

相信很多人都曾經被這個問題困擾,當然我也是這樣過來的,原來以為只要資料變了,呼叫adapter的notifyDataSetChanged就會更新列表,然而結果卻沒有實現,其實是在一些細節上沒有注意造成的,所以現在對這個問題進行下總結希望可以幫助到有需要的人。

二、原因分析

有以下三個原因:

1、資料來源沒有更新,呼叫notifyDataSetChanged無效。

2、資料來源更新了,但是它指向新的引用,呼叫notifyDataSetChanged無效。

3、資料來源更新了,但是adpter沒有收到訊息通知,無法動態更新列表。

一般來說,我們都是第二個原因造成的。

三、舉例分析

分析了原因還是直接寫個例子來說明,這樣更加清楚。 正常情況:點選新增,然後點選更新介面。
事件程式碼:
 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 = new MyAdapter(this, peopleList)
例項化MyAdapter,這裡兩個引數。點選新增後資料來源peopleList添加了兩個People物件,點選更新,實際就是呼叫notifyDataSetChanged(),listview正常更新,ok沒有問題! 接著演示個失敗的案例。
      我已經拼命點了怎麼就是沒有效果,對比上面的程式碼,發現點選失敗的case裡多了一句話,       peopleList = new ArrayList<>();        難道就是這句造成的?沒錯,就是它,也就是上面的原因2。雖然資料來源更新了,但是它指向新的引用,可是我們的Adapter繫結的還是原來資料來源的引用,自然你呼叫更新,我們的Adapter認為是沒有變化,所以失效。沒事我們重新繫結下Adapter的資料來源,開啟上面註釋的話,再來,可是結果你會發現這樣也是不行的,因為雖然Adaper是更新了資料來源,可是這個Adapter和原來的Adapter已經不一樣了,listView卻還是不知道這樣的變化,所以呼叫也會無效。
正確的做法是現在Adaper寫一個更新資料來源的方法,這樣就不會出現問題了。(上面點選通知更新的情況)
 public void setData(List<People> newPeopleList){
        this.peopleList = newPeopleList;
    }

四、總結

       上面說的這麼多,不知道大家有沒有懂,其實根本原因就是listview+adapter+資料來源這三者的繫結,如果因為指向新的引用造成三者沒有了原來的捆綁關係,自然呼叫notifyDataSetChanged()就會失效。


原始碼下載