原文网址:http://www.cnblogs.com/monodin/p/3874147.html

1、问题描述

 1 07-28 17:22:02.162: E/AndroidRuntime(16779): 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. Make sure your adapter calls notifyDataSetChanged() when its content changes. [in ListView(2131034604, class android.widget.ListView) with Adapter(class com.nodin.sarah.HeartListAdapter)]
2
3 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.ListView.layoutChildren(ListView.java:1555)
4
5 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.AbsListView.onLayout(AbsListView.java:2091)
6
7 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
8
9 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
10
11 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
12
13 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
14
15 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
16
17 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
18
19 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
20
21 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
22
23 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
24
25 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1589)
26
27 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
28
29 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
30
31 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.RelativeLayout.onLayout(RelativeLayout.java:1055)
32
33 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
34
35 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
36
37 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
38
39 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
40
41 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
42
43 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
44
45 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1671)
46
47 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1525)
48
49 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.LinearLayout.onLayout(LinearLayout.java:1434)
50
51 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
52
53 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
54
55 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.FrameLayout.layoutChildren(FrameLayout.java:453)
56
57 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.widget.FrameLayout.onLayout(FrameLayout.java:388)
58
59 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.View.layout(View.java:14785)
60
61 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewGroup.layout(ViewGroup.java:4631)
62
63 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewRootImpl.performLayout(ViewRootImpl.java:1985)
64
65 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1742)
66
67 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:998)
68
69 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5582)
70
71 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749)
72
73 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.Choreographer.doCallbacks(Choreographer.java:562)
74
75 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.Choreographer.doFrame(Choreographer.java:532)
76
77 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735)
78
79 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.os.Handler.handleCallback(Handler.java:733)
80
81 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.os.Handler.dispatchMessage(Handler.java:95)
82
83 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.os.Looper.loop(Looper.java:137)
84
85 07-28 17:22:02.162: E/AndroidRuntime(16779): at android.app.ActivityThread.main(ActivityThread.java:4998)
86
87 07-28 17:22:02.162: E/AndroidRuntime(16779): at java.lang.reflect.Method.invokeNative(Native Method)
88
89 07-28 17:22:02.162: E/AndroidRuntime(16779): at java.lang.reflect.Method.invoke(Method.java:515)
90
91 07-28 17:22:02.162: E/AndroidRuntime(16779): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
92
93 07-28 17:22:02.162: E/AndroidRuntime(16779): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
94
95 07-28 17:22:02.162: E/AndroidRuntime(16779): at dalvik.system.NativeStart.main(Native Method)
96
97 07-28 17:22:02.162: W/ActivityManager(588): Force finishing activity
 

2、复现场景

使用ListView和Adapter实现动态增删数据列表功能,初始化数据分为两部分:本地和网络。所以在Adapter的数据初始化的时候,先讲本地数据添加到了容器内。同时发起网络请求,等加载完毕后追加到容器内。
问题出现在:当网络请求完毕后追加数据的时候,抛出上述异常。
 

3、原因分析

Exception解读:
        Adapter的数据内容已经改变,但是ListView却未接收到通知。要确保不在后台线程中修改Adapter的数据内容,而要在UI Thread中修改。确保Adapter的数据内容改变时一定要调用notifyDataSetChanged()方法。
 
且不管Exception内容,先查询Android源码看看该Exception是从哪里抛出来的。
在ListView的layoutChildren()方法里有如下一段方法:
 1 // Handle the empty set by removing all views that are visible
2 // and calling it a day
3 if (mItemCount == 0) {
4 resetList();
5 invokeOnItemScrollListener();
6 return;
7 } else if (mItemCount != mAdapter.getCount()) {
8 throw new IllegalStateException("The content of the adapter has changed but "
9 + "ListView did not receive a notification. Make sure the content of "
10 + "your adapter is not modified from a background thread, but only "
11 + "from the UI thread. [in ListView(" + getId() + ", " + getClass()
12 + ") with Adapter(" + mAdapter.getClass() + ")]");
13 }
亦即,当ListView缓存的数据Count和ListView中Adapter.getCount()不等时,会抛出该异常。
 
结合开头的异常解读,可以断定肯定是Adapter数据动态更新的问题。仔细检查了自己的代码:
 
当网络请求完毕后,直接在网络线程(非UI线程)里调用了在Adapter中新增的自定义方法addData(List)更新数据,而addData(List)方法内更新换完数据后,通过Handler发送Message的策略调用Adapter的notifyDataSetChanged()方法通知更新。
 
这么一来,并不能保证Adapter的数据更新时,立马调用notifyDataSetChanged()通知ListView,这两个线程之间的时间差引起的数据不同步,导致ListView的layoutChildren()中访问Adapter的getCount()方法时,Adapter内已经是最新数据源,而ListView内的缓存数据Count仍是旧数据的Count,该问题最终原因终于浮出水面。
 

4、解决方案

在本例中,解决方案是:把addData(List)方法内更新数据的代码挪出来,和notifyDataSetChanged()方法一同放在Handler里,保证数据更新时及时通知ListView。
 
为了尽量避免该问题,以后编程尽量从如下几个方面检查自己的代码:
  • 确保Adapter的数据更新后一定要调用notifyDataSetChanged()方法通知ListView
  • 数据更新和notifyDataSetChanged()放在UI线程内,且必须同步顺序执行,不可异步
  • 仔细检查确认getCount()方法返回值是否正确

【转】关于Adapter的The content of the adapter has changed问题分析 关于Adapter的The content of the adapter has changed问题分析的更多相关文章

  1. I have Flash Player installed, but I am unable to view Flash content in Chromium. How do I enable Flash Player to view this content?

    I have Flash Player installed, but I am unable to view Flash content in Chromium. How do I enable Fl ...

  2. 包含了重复的“Content”项。.NET SDK 默认包含你项目目录中的“Content”项。可从项目文件中删除这些项;如果希望将其显式包含在项目文件中,可将“EnableDefaultContentItems”属性设置为“false”

    从.netcore 1.1 升级到2.0时遇到该问题. 参考http://www.cnblogs.com/xishuai/p/visual-studio-for-mac.html 根据提示可知(我是看 ...

  3. Android开发-API指南-创建 Content Provider

    Creating a Content Provider 英文原文:http://developer.android.com/guide/topics/providers/content-provide ...

  4. Android开发-API指南-Content Provider基础

    Content Provider Basics 英文原文:http://developer.android.com/guide/topics/providers/content-provider-ba ...

  5. Android中的Adapter 详解

    http://blog.csdn.net/tianfeng701/article/details/7557819 (一) Adapter介绍 Android是完全遵循MVC模式设计的框架,Activi ...

  6. Content Provider Basics ——Content Provider基础

    A content provider manages access to a central repository of data. A provider is part of an Android ...

  7. Dhroid框架笔记(DhNet、Adapter)

    3.1.1 DhNet用于获取网络中的数据 DhNet net=new DhNet("路劲"); net.addParam("key", "参数&qu ...

  8. Android应用程序组件Content Provider应用实例

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6950440 文简要介绍了Android应用程序 ...

  9. android-适配Adapter

    Adapter是把数据和用户界面视图绑定到一起的桥梁类,负责创建用来表示父视图中的每一个条目的子视图,并提供对底层数据的访问. public class MainActivity extends Ac ...

  10. 我的Android 4 学习系列之数据库和Content Provider

    目录 创建数据库和使用SQLite 使用Content Provider.Cusor和Content Value来存储.共享和使用应用程序数据 使用Cursor Loader异步查询Content P ...

随机推荐

  1. [LeetCode] 110. Balanced Binary Tree 解题思路

    Given a binary tree, determine if it is height-balanced. For this problem, a height-balanced binary ...

  2. 【KMP】Number Sequence

    KMP算法 KMP的基处题目,数字数组的KMP算法应用. 主要是next[]数组的构造,next[]存储的是字符的当前字串,与子串前字符匹配的字符数. 移动位数 = 已匹配的字符数 - 对应的部分匹配 ...

  3. [教程] 神器i9100刷基带与内核的方法!(兼带ROOT方法)

    http://bbs.hiapk.com/thread-2647905-1-1.html ------何为基带?何为内核? 为什么刷基带,为什么刷内核?!!! 基带:基带(Baseband)是手机中的 ...

  4. (转)鸟哥SHELL入门材料

    http://blog.chinaunix.net/space.php?uid=9809038&do=blog&cuid=62903 经典入门材料! 学习 Shell Scripts ...

  5. java(17) - 增强for循环、装箱拆箱、可变参数

    一.增强型for循环: 语法格式: 打印: A B C D E 当遍历集合或数组时,如果需要访问集合或数组的下标时,最好使用旧的方法来便利或循环,而不要用增强型for循环,因为它丢失了下标信息. 对于 ...

  6. Java虚拟机之垃圾回收详解一

    Java虚拟机之垃圾回收详解一 Java技术和JVM(Java虚拟机) 一.Java技术概述: Java是一门编程语言,是一种计算平台,是SUN公司于1995年首次发布.它是Java程序的技术基础,这 ...

  7. 为什么要使用Nginx?

    这里做了些基准测试表明nginx打败了其它的轻量级的web服务器和代理服务器,同样也赢了相对不是那么轻量级的产品. 有人说这些基准测试是不准确的,因为在这样那样的环境下,做的比较不一致.我倾向同意基准 ...

  8. 第12届北师大校赛热身赛第二场 A.不和谐的长难句1

    题目链接:http://www.bnuoj.com/bnuoj/problem_show.php? pid=17121 2014-04-25 22:59:49 不和谐的长难句1 Time Limit: ...

  9. [Typescript] Function defination

    Define a function type and params type: // The function init // Accept two params which are both typ ...

  10. C#自定义List类

    代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Text; namespac ...