近期工作中,发现了一个bug,是和ListView Adapter有关的。产生了FC,描写叙述信息大约是

"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(xxx) with Adapter(HeaderViewListAdapter)]"

它的大意是,Adapter内的数据发生了变化,可是UI却没有更新,您是否忘记调用了notifyDataSetChanged?

这实际上是一个很有误导的信息。普通情况下,我们不会忘记调用该函数的。可是假设我们不小心,从listview继承一个新的类,并override它的getAdapter方法,就可能会出问题了。

ListView是支持HeaderView和footerView的,即在listview的最初和最末尾的位置加入�一些特殊的view。它的实现方法,就是通过一个HeaderViewListAdapter。

HeaderViewListAdapter会包装一个Adapter,这个是由用户自己设置的。ListView中相应的代码是

    @Override
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
} resetList();
mRecycler.clear(); if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}

ListView的getAdapter返回的是mAdapter,就可以能是一个HeaderViewListAdapter.

假设override getAdapter,并返回HeaderViewListAdapter内部包装的Adapter,就会出问题。也就是上面提到的FC.

这样的问题是怎么出现呢?

首先,这个异常抛出的位置,是在函数layoutChildren中,抛出的条件是mItemCount != mAdapter.getCount(),代码例如以下:

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() + ")]");
}

那么mItemCount的值是在哪里赋值呢?mItemCount不是ListView的成员,而是ListView的超超类:AdapterView的成员,这个值也是在DataObserver.onChanged中设置的,您可參考AdapterView的源代码:

class AdapterDataSetObserver extends DataSetObserver {

        private Parcelable mInstanceState = null;

        @Override
public void onChanged() {
mDataChanged = true;
mOldItemCount = mItemCount;
mItemCount = getAdapter().getCount(); //这里!注意使用方法getAdapter() // Detect the case where a cursor that was previously invalidated has
// been repopulated with new data.
if (AdapterView.this.getAdapter().hasStableIds() && mInstanceState != null
&& mOldItemCount == 0 && mItemCount > 0) {
AdapterView.this.onRestoreInstanceState(mInstanceState);
mInstanceState = null;
} else {
rememberSyncState();
}
checkFocus();
requestLayout();
}

假设 getAdapter() != mAdapter就会发生故障:getAdatper返回的是mAdapter(即HeaderListViewAdapter),那么,mAdapter.getCount() == getAdapter().getCount() + header view count + footer view count.

出现上面的问题就在所难免了。

Override ListView getAdapter造成的后果的更多相关文章

  1. 关于ScrollView嵌套ListView问题

    Android开发之ScrollView中嵌套ListView的解决方案   原文:http://blog.csdn.net/minimicall/article/details/40983331   ...

  2. ScrollView中嵌套GridView,ListView只显示一行的解决办法

    转载:http://blog.csdn.net/luohai859/article/details/39347583 关于为什么只显示一行,个人理解是:如果单独使用GridView和ListView, ...

  3. 双击导航栏自动滑动ListView到顶部

    有些app都实现了双击导航栏让页面的list自动滑动到顶部的feature. 先实现一个继承于OnTouchListener的监听多次点击事件的监听器,通过callback把连续点击的次数返回给客户代 ...

  4. 安卓中級教程(4):ScrollView與ListView之間的高度問題

    在scrollView中加插ListView是一個大難題.其中一個難題是Listview的高度難以計算,輸出效果往往強差人意,就讓我們看看當中的問題 . <LinearLayout xmlns: ...

  5. Android listview addHeaderView 和 addFooterView 详解

    addHeaderView()方法:主要是向listView的头部添加布局addFooterView()方法:主要是向listView的底部添加布局 需要注意的是添加布局的时候应该添加从父容器开始添加 ...

  6. ScrollView与ListView冲突解决

    正 常来说,在ScrollView添加一个ListView后在真机上只会显示ListView的一行多一点,我也不理解为什么会这样,后来我把 ListView的layout_height改成400dip ...

  7. 四种方案解决ScrollView嵌套ListView问题(转)

    以下文章转自@安卓泡面 在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全.我试过很多种方法,它们各有利弊. 在这里我将会从使用ScrollVie ...

  8. 解决ScrollView嵌到listView冲突问题

    方法一: 把下面的方法放在绑定适配器操作的下面就行. /** * 重新计算ListView的高度,解决ScrollView和ListView两个View都有滚动的效果,在嵌套使用时起冲突的问题 * @ ...

  9. ListView和ScrollView冲突

    当ListView放在ScrollView中的时候,无论你设置高度为 match_parent(填充父窗体)和wrap_content(包裹内容)都只显示一行,这是你把ListView放在Linear ...

随机推荐

  1. ASP.NET在主题中添加CSS文件

    ASP.NET在主题中添加CSS文件 在ASP.NET中,可以使用CSS来控制页面上HTML元素和ASP.NET控件的皮肤.如果在主题文件夹中添加了CSS文件,则在页面应用主题时也会自动应用CSS. ...

  2. Java集合类之LinkedList链表

    package com.test; import java.util.*; public class Demo7_3 { public static void main(String[] args) ...

  3. 自定义的IntentFileter 无法找到activity

    <intent-filter > <action android:name="com.leo.enjoytime.VIEW"/></intent-fi ...

  4. 分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码

    先回顾一下classpath classpath的作用: classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类. 指 ...

  5. YII CJson类

    CJson文档: http://www.yiiframework.com/doc/api/1.1/CJSON CJson::encode可以编码任何类型的数据:源码如下: public static ...

  6. MySQL的SQL_CALC_FOUND_ROWS

    分页程序一般由两条SQL组成: SELECT COUNT(*) FROM ... WHERE .... SELECT ... FROM ... WHERE LIMIT ... 如果使用SQL_CALC ...

  7. 手势识别官方教程(2)识别常见手势用GestureDetector+手势回调接口/手势抽象类

    简介 GestureDetector识别手势. GestureDetector.OnGestureListener是识别手势后的回调接口.GestureDetector.SimpleOnGesture ...

  8. UltraEdit (Ctrl + F) 查找、(Ctrl + R)替换功能失效

    环境: Windows 7 Service Pack 1 X64 工具: UltraEdit Version 21 症状: UltraEdit (Ctrl + F) 查找.(Ctrl + R)替换功能 ...

  9. 360手机助手内部资料曝光,63张PPT纯干货

    360手机助手内部资料曝光,63张PPT纯干货 日前,国内最大的安卓应用商店360手机助手发布了<2016年手机软件行业趋势绿皮书>,这份绿皮书对2015年以来移动互联网的趋势做了总结,展 ...

  10. bzoj1084

    乍一看这题好难,根本不会: 直到看到1<=m<=2…… 显然分类讨论dp, 很快想到这题的dp和poj2430相类似 m=2的时候f[i,j,k]表示到第i行用了j个矩阵结尾状态为k时最大 ...