贴出源代码:

android.widget.ListView

...

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. "+"Make sure your adapter calls notifyDataSetChanged() when its content changes. "+"[in ListView(" +getId() +"", + getClass + ") with Adapter(" + mAdapter.getClass+ ")]");
}

...

今天看见这个异常百思不得其解,幸好在论坛上看见一位牛人的解析,瞬间明了。

原文分析:

普通情况下。上述异常一般发生在我们启动一个后台线程载入数据,同一时候在主线程(即UI线程)刷新ListView在显示新载入的内容。

我们的做法通常是:在后台线程中把载入的数据放入到一个List中,而在主线程中实例化Adapter,这个Adapter中所用到的List正是在后台线程中载入的那个List。

发生上述异常的代码思路是这样子的。请看代码:

首先,我们定义一个List全局变量,后台线程中载入的数据就放到这个list中(请注意我标了红色的list变量,问题就出在它身上):

private List<Map<String,Object>> list = null;

接着,我们会启动一个后台线程,用于载入数据:

class GetDataThread implements Runnable{//单独启动一个线程用于载入歌曲列表

@Override
        public void run() {
            list = new ArrayList<Map<String,Object>>();

//然后把搜索出来的数据放入到list中。

}
 }

最后,我们会在主线程中刷新界面。刷新界面的代码。我们是要放到handler中处理的:

class RefreshLocalMusicListThread implements Runnable{

@Override
  public void run() {
        local_lv = (ListView)findViewById(R.id.local_musiclist);

SimpleAdapter adapter = new SimpleAdapter(LocalActivity.this,list,R.layout.local_music_list,new String[]     {"local_name","local_size"}, new int[]{R.id.local_name,R.id.local_size});
        local_lv.setAdapter(adapter);
        LocalActivity.this.registerForContextMenu(local_lv);
        handler.postDelayed(refreshThread, 10);

}

}

以上的思路,是会发生上述异常的!

以下请看我的分析:

当执行 SimpleAdapter adapter = new SimpleAdapter(LocalActivity.this,list,R.layout.local_music_list,new String[] {"local_name","local_size"}, new int[]{R.id.local_name,R.id.local_size});时集合list中数据与我们的listView是绑定在一起的了。

此时。,假如list中的数据有5条,即list.size()==5,这时与listView绑定的就是5条数据。可是,我们的后台线程还在执行,list中的数据会发生变化,然而我们的listView认定的就是之前仅仅有5条数据的list,可是这时的list中的数据已经不是5条了。就是这个冲突导致了上述的异常!!!发生在else if()推断语句处

网上有这样一种解决方法(实际上解决不了问题):

在 adapter.notifyDataSetChanged() 之前调用listview.setVisibility(View.GONE);在adapter.notifyDataSetChanged() 之后调用listview.setVisibility(View.VISIBLE)

可是这是错误的!!


正确的解决方法是这种:

既然与listView绑定了的list发生了变化而没来得及通知listView导致了上述的异常,那我们就针对这一点,仅仅要listView与list绑定后,在listView显示之前不要让list发现变化即可了。做法有非常多种。我个人的做法是这样子的:

首先,定义一个独立的List:

private List<Map<String,Object>> data = null;

接着,在onCreate或者onResume中初始化它(当然,你也能够在每次用到它的时候初始化它。只是这样子会初始化非常多对象,浪费内存,不推荐):

data = new ArrayList<Map<String,Object>>();

然后,在创建adapter之前,把list中数据放入到集合data中。注意千万不要直接赋值:data = list(这是错误的。由于这样data也指向了list所在的内存地址,即data跟list是同一个对象。list改变的话data也跟着改变)。应该这么做:

data.clear();//要先清空data中的数据。避免把list中的数据反复放入data中。

data.addAll(list);//这样做。list中的数据就放入到data中,之后list在后台线程中改变,但data不会改变,这时,你再

SimpleAdapter adapter = new SimpleAdapter(LocalActivity.this,data,R.layout.local_music_list,new String[] {"local_name","local_size"}, new int[]{R.id.local_name,R.id.local_size});

listView与data绑定,就不会发生上述异常了!

总结来说。即创建一个缓存变量。存储的值是第一次查询得到数据 ,后台线程继续查询出来的数据不再使用。如此就保证了显示数据时不会报出异常。

转载于:https://www.cnblogs.com/bhlsheji/p/5101781.html

ListView IllegalStateException相关推荐

  1. android开发过程中遇到的问题

    记录android开发过程中遇到的问题. 1.在一个xml中能否使用同一个include多次 http://www.apkbus.com/android-104152-1-1.html android ...

  2. 记录的Android开发过程中遇到的问题。

    180508  更新 网上下载demo 本地studio版本和demo版本不一致处理方式 修改两处 1 项目的build.gradle 里面classpath 2修改项目目录下 gradle--> ...

  3. 关于viewpager 里嵌套 listview 同时实现翻页功能的“java.lang.IllegalStateException: The specified child...异常处理...

    这几天做项目用到了ViewPager,因为它可以实现左右划动多个页面的效果,然后 再每个页面里使用ListView,运行时总是出现"PagerAdapter java.lang.Illega ...

  4. 解决java.lang.IllegalStateException: The content of the adapter has changed but ListView...的问题

    我写了一个Dialog,Dialog中有一个ListView,想要点ListView中的一项后,跳转到另外一个Activity去. 但在使用时,会偶尔报出下面的错误: 02-21 14:54:28.9 ...

  5. 完美解决 ListView偶尔爆出的异常:java.lang.IllegalStateException

    在我们Android 开发中,ListView是在常用不过的控件了.但是有时候会爆出这种异常,就搞得好尴尬了. 明明我们在代码中的确是有调用adaptor.notifyDataSetChanged() ...

  6. 自定义BaseAdapter完美解决ListView异常:java.lang.IllegalStateException

    2019独角兽企业重金招聘Python工程师标准>>> 在我们Android 开发中,ListView是在常用不过的控件了.但是有时候会爆出这种异常,就搞得好尴尬了. 明明我们在代码 ...

  7. ListView通过自定义的Adapter实现异步下载显示网络图片

    为什么80%的码农都做不了架构师?>>>    先说一下思路,开始让一张放在res/drawable里的图片代替网络图片,加进ListItem,现在显示的就是本地图片,然后新开一个线 ...

  8. 源码之ListView分析

    转载请注明出处:http://blog.csdn.net/guolin_blog/article/details/44996879 在Android所有常用的原生控件当中,用法最复杂的应该就是List ...

  9. 关于Adapter的The content of the adapter has changed but ListView did not receive a notification.问题分析

    1.问题描述 1 07-28 17:22:02.162: E/AndroidRuntime(16779): java.lang.IllegalStateException: The content o ...

最新文章

  1. 腾讯的人工智能大战已然打响!
  2. 用户 ‘IIS APPPOOL\IdealTest‘ 登录失败解决方案
  3. @ngrx入坑angular的schema,爽的一逼!
  4. python 将YOLO(txt)格式的标注数据批量转换为PascalVOC(XML)格式的标注数据
  5. 【01】Clean Code
  6. mysql semi-synchronous_MySQL Semisynchronous Replication介绍
  7. MySQLdb安装的错误说明
  8. 前端学习(1709):前端系列javascript之uniapp
  9. java mediainfo.dll_MediaInfo库的简单使用
  10. Windows下最轻量级Git克隆工具源码分享
  11. oracle设置no null,Oracle 在not in中使用null的问题
  12. v-distpicker 直辖市的修改
  13. 科创板IPO申报期间新增技术认定,研发费用真实性被质疑,这公司注册阶段终止审核
  14. 计算机整个文稿应用回顾主题,计算机应用基础(MS Office高级应用)
  15. word使用的奇技淫巧
  16. 谈谈MySQL如何选择float, double, decimal
  17. Excel表格函数(3)
  18. 五十三 九环山遇鬼(上)我在软件园的那些日子里
  19. 我眼中的 Nginx(一):Nginx 和位运算
  20. TwinCAT3 安装包,吃了没文化的亏……手动捂脸

热门文章

  1. setTimeOut与setInterval的区别
  2. 第0章 前言(续1)
  3. 如何用木板做桥_为这份动手能力点赞!旧木板打磨后做成橱柜,效果可媲美定制的...
  4. pythondef元组参数传递_Python参数传递(传值传引用)
  5. 阈值和阀值的区别_基于双阈值设定的图像识别产品策略
  6. Zookeeper概述详细解释(Zookeeper3.6)
  7. 11Linux_vmtools
  8. mysql maria引擎_MySQL/MariaDB---查询缓存与存储引擎
  9. cv mat 灰度值和_c++ 访问OpenCV中灰度图像的像素值
  10. extjs 方法执行顺序_百战程序员:方法论