java.lang.IllegalStateException:Make sure the content of your adapter is not modified from a backgro

来源:互联网 发布:ubuntu挂载网络硬盘 编辑:程序博客网 时间:2024/05/24 00:16

java.lang.IllegalStateException:Make sure the content of your adapter is not modified from a background thread, but only from the UI thread
的意思大体是,你的adapter的内容变化了,但是你的ListView并不知情。请保证你adapter的数据在主线程中进行更改!
初看这个问题感觉很简单.不就是没有在主线程更新ui吗? hander  .runOnUiThread 走起,发现,尼玛,都是在主线程啊,怎么回事,我的notifyChange 都是在主线程更新ui,怎么还报这个错!!!  看了网上的分析
 分析的后别的博客大神做了如下改动:
相对于原来,我做了两项改动:
1.将所有数据“完全”保存在adapter内部,即使有外部数据进入,也会用.clone()重新生成副本,保证了数据完全是由adapter维护的。
2.保证所有setDeviceList()/clearDeviceList()是从主线程里调用的,如何保证是从主线程中调用的呢:
  a.调用Activity.runOnUIThread()方法;
  b.使用Handler(其实这并不非常准确,因为Handler也可以运行在非UI线程);
  c.使用AsyncTask。

  
 源码:
在ListView的layoutChildren()方法里有如下一段方法:
// Handle the empty set by removing all views that are visible
// and calling it a day
if (mItemCount == 0) {
    resetList();
    invokeOnItemScrollListener();
    return;
} else if (mItemCount != 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() + ")]");
}
意思是:当ListView缓存的数据Count和ListView中Adapter.getCount()不等时,会抛出该异常。
博客二的解决办法:
彻底解决方法:
把  listview的adapter数据更新和dapter.notifyDataSetChanged()方法的调用必须同时放到单独一个线程里,报错基本是都是这个原因,有人把adapter里的数据更新了,但是 dapter.notifyDataSetChanged() 放到一个单独线程去更新,结果出现notifyDataSetChanged更新同步的问题
以上内容来自:http://blog.csdn.net/changemyself/article/details/8116670
 
解决更新ListView数据时出现的问题分析总结:
  没仔细读的话,一眼看去就说说在非UI线程去更新了ListVIew的数据,然后下意识的认为是调用adapter.notifyDataSetChanged方法的调用被放到了非UI线程,仔细一看是说更新ListView的数据以及通知数据更新要放到同一个线程(主线程),是为了保持数据一致,adapter里面一般是会存放一个数组,对那个数据的修改和调用notifyDataSetChanged方法要放到一起,而且是放到主线程,如果对数据的更新放到了子线程,notifyDataSetChanged的调用在主线程,notifyDataSetChanged的调用会默认把ListView绑定到主线程里面了,这个时候子线程来更新数据的话就会出现在非UI线程修改UI线程的东西了。

这个问题也不是必崩溃,低版本崩的多,高版本好像崩溃得少
博客三的解决办法:
 
我的adapter数据是保存在mlist中,而在代码中不断的改变了mlist内部的数据,而只在最后调用了一次mAdapter.notifyDataSetChanged(),导致listview没有及时刷新而抛出异常。
所以结论在使用listview时,及时不在非ui线程中更新adapter数据,也最好将数据直接定义在adapter类内部或在改变数据时要及时刷新listview,否则会抛出上述异常。
博客四的解决办法:
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()。然后重新更新加载数据,这样一般可以解决问题。 

我的原因: 
我改变了数据集,比如我把数据全清空了userBooks.clear(),这个时候我没有及时调用adapter.notifyDataSetChanged(),会导致ListView没有数据而抛java.lang.IllegalStateException这个异常。 
记住,当改变了数据集之后,需要及时adapter.notifyDataSetChanged() 
也就是说,这2句话需要写在一起: 
Java代码  
  1. userBooks.clear();  
  2.         if(adapter!=null){  
  3.             adapter.notifyDataSetChanged();  
  4.         }  
 其实截取这么多!
     发现,自己的问题,前面的三个都解决不了, 自己的问题出在第四个问题点上,之前一直检查的都是请求成功后的数据变化,没有考虑到当发出请求的时候,就把数据给清除掉了,并且没有通知刷新,,测试又对其进行狂点, 这个时候集合中的数据是空的, 而adapter中的getcount还是之前的,导致问题的,数据出现空窗期,从而导致问题的出现, 
  最后把情况数据的代码放到请求成功的回调里面,当curPage等于零的时候,再clear,再次狂点,并切换,问题不会再次出现,该问题得到了圆满的解决!!!
  
阅读全文
0 0