Android问题3-ListView Adapter(The content of the adapter has changed but ListView did not receive a n)
2012-11-21 14:03
471 查看
在Android编程中使用Adapter时,偶尔会出现如下错误:
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。
DDMS中的log也无法定位到准确的出错位置。检查错误可以从下面几点入手:
1、检查Thread,确定没有在Background thread中直接调用adapter,如果有,请移除相关代码到Handler中处理;
2、尽量将数据放在adapter类中管理,不需要的时候清除信息(勤写clear()),及时用notifyDataSetChanged()刷新;
3、在Activity或者Fragment合适的位置(onPause/onStop)要及时检查thread,有adapter数据处理相关的应马上停止;
4、这个错误经常出现在Activity休眠起来之后,主要还是使用adapter不太小心造成的。如果实在找不到原因,在onPause()函数中停止所有的background thread,并且在onResume()函数最前面清空adapter中的数据,并且adapter.notifyDataSetChanged()。然后重新更新加载数据,这样一般可以解决问题。
很多新手在Android开发时可能对Thread和Message以及Handler、Looper概念不是很清楚,可能产生类似
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.的错误。在这里给出以下几点可以帮助你了解该问题:
1.改变适配器Adapter内容时不要在后台线程中,必须在UI线程中处理,这点可以通过Handler传出来解决。
2.尝试Adapter的notifyDataSetChanged()方法,当然主要看你代码的具体情况。
以上只貌似只是把错误信息翻译过来而已,真正的原因请看源代码:
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
..... //中间是其他代码就不拷贝了
else if (mItemCount != mAdapter.getCount()) {//这里可以看出为什么会抛出adapter has changed,是因为你可能还有线程在跑,更新了mAdapter.getCount();的返回值
throw new 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. [in ListView(" + getId() + ", " + getClass()
+ ") with Adapter(" + mAdapter.getClass() + ")]");
复制代码
ps:知其然,知其所以然。刚开始我发现写不写notifyDataSetChanged()都能实现效果,于是我就把它注释了,直到出了问题,我看了以上内容,我就明白为什么会有adapter
has changed的提示,也明白了notifyDataSetChanged()的含义。
我的理解是:增加了内容长度改变了 但是没有通知更新 当选中增加的那个内容时 就造成了 数组越界(或者别的问题)
在Android开发过程中,使用了大量的ListView,发现这个错误偶尔会出现。特别是做压力测试的时候,不停的点击刷新,更容易出现这个错误。代码中已经使用了Adapter的notifyDataSetChanged()方法通知UI更新了,但是还是会出现这个错误。究其根本原因,还是线程之间同步的问题。比如,线程1更新了Adapter中的内容,却还没有来得及通知内容已经更新,就又有线程2更新了Adapter中的内容,这个时候如果线程1再通知内容更新,就会出现上述异常了。
在此提出一些解决办法:
对线程进行管理,如果当前Actitivty暂停了,及时停止这些线程。
数据更新后,要及时使用notifyDataSetChanged()方法通知UI,避免出现数据不一致的情况。
数据的更新,最好放在主线程中进行。这样可以使用同步数据更新与通知内容更新部分的代码。
示例代码:
[java] view
plaincopy
if(recThread == null){
recThread = new Thread(){
@Override
public void run(){
}
};
}
if(!recThread.isAlive()){
recThread.start();
}
[java] view
plaincopy
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Friends.stopRecThread();
Log.d("meng", "onPause2");
}
[java] view
plaincopy
public static void stopRecThread(){
if(recThread!=null){
recThread.interrupt();
recThread = null;
}
}
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。
DDMS中的log也无法定位到准确的出错位置。检查错误可以从下面几点入手:
1、检查Thread,确定没有在Background thread中直接调用adapter,如果有,请移除相关代码到Handler中处理;
2、尽量将数据放在adapter类中管理,不需要的时候清除信息(勤写clear()),及时用notifyDataSetChanged()刷新;
3、在Activity或者Fragment合适的位置(onPause/onStop)要及时检查thread,有adapter数据处理相关的应马上停止;
4、这个错误经常出现在Activity休眠起来之后,主要还是使用adapter不太小心造成的。如果实在找不到原因,在onPause()函数中停止所有的background thread,并且在onResume()函数最前面清空adapter中的数据,并且adapter.notifyDataSetChanged()。然后重新更新加载数据,这样一般可以解决问题。
很多新手在Android开发时可能对Thread和Message以及Handler、Looper概念不是很清楚,可能产生类似
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.的错误。在这里给出以下几点可以帮助你了解该问题:
1.改变适配器Adapter内容时不要在后台线程中,必须在UI线程中处理,这点可以通过Handler传出来解决。
2.尝试Adapter的notifyDataSetChanged()方法,当然主要看你代码的具体情况。
以上只貌似只是把错误信息翻译过来而已,真正的原因请看源代码:
mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
..... //中间是其他代码就不拷贝了
else if (mItemCount != mAdapter.getCount()) {//这里可以看出为什么会抛出adapter has changed,是因为你可能还有线程在跑,更新了mAdapter.getCount();的返回值
throw new 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. [in ListView(" + getId() + ", " + getClass()
+ ") with Adapter(" + mAdapter.getClass() + ")]");
复制代码
ps:知其然,知其所以然。刚开始我发现写不写notifyDataSetChanged()都能实现效果,于是我就把它注释了,直到出了问题,我看了以上内容,我就明白为什么会有adapter
has changed的提示,也明白了notifyDataSetChanged()的含义。
我的理解是:增加了内容长度改变了 但是没有通知更新 当选中增加的那个内容时 就造成了 数组越界(或者别的问题)
在Android开发过程中,使用了大量的ListView,发现这个错误偶尔会出现。特别是做压力测试的时候,不停的点击刷新,更容易出现这个错误。代码中已经使用了Adapter的notifyDataSetChanged()方法通知UI更新了,但是还是会出现这个错误。究其根本原因,还是线程之间同步的问题。比如,线程1更新了Adapter中的内容,却还没有来得及通知内容已经更新,就又有线程2更新了Adapter中的内容,这个时候如果线程1再通知内容更新,就会出现上述异常了。
在此提出一些解决办法:
对线程进行管理,如果当前Actitivty暂停了,及时停止这些线程。
数据更新后,要及时使用notifyDataSetChanged()方法通知UI,避免出现数据不一致的情况。
数据的更新,最好放在主线程中进行。这样可以使用同步数据更新与通知内容更新部分的代码。
示例代码:
[java] view
plaincopy
if(recThread == null){
recThread = new Thread(){
@Override
public void run(){
}
};
}
if(!recThread.isAlive()){
recThread.start();
}
[java] view
plaincopy
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
Friends.stopRecThread();
Log.d("meng", "onPause2");
}
[java] view
plaincopy
public static void stopRecThread(){
if(recThread!=null){
recThread.interrupt();
recThread = null;
}
}
相关文章推荐
- Android The content of the adapter has changed but ListView did not receive a notification
- ListView数据源不同步问题The content of the adapter has changed but ListView did not receive a notification.
- 问题解决:The content of the adapter has changed but ListView did not receive a notification
- 【Android策略】The content of the adapter has changed but ListView did not receive a notification
- 解决问题The content of the adapter has changed but ListView did not receive a notification.
- Android - Bug:The content of the adapter has changed but ListView did not receive a notification.
- android报The content of the adapter has changed but ListView did not receive a notification的解决方案
- 关于Adapter的The content of the adapter has changed but ListView did not receive a notification.问题分析
- Android开发-- The content of the adapter has changed but ListView did not receive a notification - With AsyncTask
- android The content of the adapter has changed but ListView did not receive a notification 错误的解决方案
- 解决ListView的The content of the adapter has changed but ListView did not receive a notification崩溃问题
- listview刷新点击,出现The content of the adapter has changed but ListView did not receive a notification问题
- 在线程汇总更新UI的注意问题The content of the adapter has changed but ListView did not receive a notification. Ma
- 解决The content of the adapter has changed but ListView did not receive a notification的问题
- 【遇见Android bug】The content of the adapter has changed but ListView did not receive a notification
- Adapter报错:The content of the adapter has changed but ListView did not receive a
- The content of the adapter has changed but ListView did not receive a notification. Make sure the co
- The content of the adapter has changed but ListView did not receive a notification 错误的解决方案
- The content of the adapter has changed but ListView did not receive a notification 异常解决
- 处理The content of the adapter has changed but ListView did not receive a notification异常