java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. ...
ListView遇到频繁更新数据源并显示时报错
adapter里面的数据更新(content)不能在在后台,否则会概率性的报错,报错一般因为更新数据源和notifyDataSetChanged不在一个线程上
一些解决方法:
对线程进行管理,如果当前Actitivty暂停了,及时停止这些线程。
数据更新后,要及时使用notifyDataSetChanged()方法通知UI,避免出现数据不一致的情况。
数据的更新,最好放在主线程中进行。这样可以使用同步数据更新与通知内容更新部分的代码。
在用到多线程的时候,可以对数据做缓存处理, 比如与ListView绑定的数据存储在ArrayList (dataList), 在线程中先将数据加入到临时ArrayList(tmpList) , 最后在调用notifyDataSetChanged()方法通知UI更新之前, 把临时ArrayList(tmpList)中的数据更新到ArrayList(dataList)中, 然后清空临时ArrayList(tmpList)数据。
/*
相对于原来,我做了两项改动:
1.将所有数据“完全”保存在adapter内部,即使有外部数据进入,也会用.clone()重新生成副本,保证了数据完全是由adapter维护的。
2.保证所有setDeviceList()/clearDeviceList()是从主线程里调用的,如何保证是从主线程中调用的呢:
a.调用Activity.runOnUIThread()方法;
b.使用Handler(其实这并不非常准确,因为Handler也可以运行在非UI线程);
c.使用AsyncTask。
*/
private class DeviceAdapter extends BaseAdapter {
private LayoutInflater inflater;
private ArrayList<Device> devices;
public DeviceAdapter() {
inflater = LayoutInflater.from(mContext);
}
@SuppressWarnings("unchecked")
public void setDeviceList(ArrayList<Device> list) {
if (list != null) {
devices = (ArrayList<Device>) list.clone();
notifyDataSetChanged();
}
}
public void clearDeviceList() {
if (devices != null) {
devices.clear();
}
notifyDataSetChanged();
}
@Override
public int getCount() {
return devices == null ? 0 : devices.size();
}
//以下略...