天天看点

坑人的The content of the adapter has changed but ListView did not receive a notification.

pri

private void init(){
    adapter = new DataListAdapter(list);
    listView.setAdapter(adapter);
}

private Handler handler = new Handler() {
    @Override
    public void handleMessage(@NonNull Message msg) {
        switch (msg.what) {
            case 0:
                adapter.notifyDataSetChanged();
                break;
        }
    }
};

@Override
public void onSuccess(String result, String path) throws IOException {
    Data data = new Data();
    ...
    list.add(data);
    handler.sendEmptyMessage(0);
}
           

有没有像我这样觉得,子线程动态修改list内容后,明明我已经把listview的更新操作通过handler交给UI线程(主线程)了,为什么还报这个错误!!!!!

别急,这是因为你遇到 同步 的问题了。

直接说解决办法吧,需要改变Adapter的设置数据方式,我们总是习惯在构造函数里直接把数据传给adapter,这样不行,我们要改变一下方式,如下OK ↓ ↓ ↓ ↓ ↓

public class CodeListAdapter extends BaseAdapter {
    private List<CodeInfo> list;
    ...

    public CodeListAdapter() {
        ...
    }

    public void setData(List<CodeInfo> list) {
        if (list != null) {
            if (this.list == null) {
                this.list = new ArrayList<>();
            } else {
                this.list.clear();
            }
            this.list.addAll(list);
            notifyDataSetChanged();
        }
    }

    @Override
    public int getCount() {
        return list == null ? 0 : list.size();
    }

    ...
}
           

使用方式 ↓ ↓ ↓ ↓ ↓

public class InStorageQuickActivity extends BaseActivity {

    private CodeListAdapter adapter;
    private List<CodeInfo> list = new ArrayList<>();
    ...

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case 0:
                    adapter.setData(list);
                    break;
            }
        }
    };


    @Override
    protected void init() {
        adapter = new CodeListAdapter();
        adapter.setData(list);
        listview.setAdapter(adapter);
    }

    ...

    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            ...
            CodeInfo info = new CodeInfo();
            info.no = codeList.size();
            info.code = code;
            list.add(info);
            handler.sendEmptyMessage(0);
        }
    };
}
           

这样就再也不会报错了