Override ListView getAdapter造成的后果
近期工作中,发现了一个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造成的后果的更多相关文章
- 关于ScrollView嵌套ListView问题
Android开发之ScrollView中嵌套ListView的解决方案 原文:http://blog.csdn.net/minimicall/article/details/40983331 ...
- ScrollView中嵌套GridView,ListView只显示一行的解决办法
转载:http://blog.csdn.net/luohai859/article/details/39347583 关于为什么只显示一行,个人理解是:如果单独使用GridView和ListView, ...
- 双击导航栏自动滑动ListView到顶部
有些app都实现了双击导航栏让页面的list自动滑动到顶部的feature. 先实现一个继承于OnTouchListener的监听多次点击事件的监听器,通过callback把连续点击的次数返回给客户代 ...
- 安卓中級教程(4):ScrollView與ListView之間的高度問題
在scrollView中加插ListView是一個大難題.其中一個難題是Listview的高度難以計算,輸出效果往往強差人意,就讓我們看看當中的問題 . <LinearLayout xmlns: ...
- Android listview addHeaderView 和 addFooterView 详解
addHeaderView()方法:主要是向listView的头部添加布局addFooterView()方法:主要是向listView的底部添加布局 需要注意的是添加布局的时候应该添加从父容器开始添加 ...
- ScrollView与ListView冲突解决
正 常来说,在ScrollView添加一个ListView后在真机上只会显示ListView的一行多一点,我也不理解为什么会这样,后来我把 ListView的layout_height改成400dip ...
- 四种方案解决ScrollView嵌套ListView问题(转)
以下文章转自@安卓泡面 在工作中,曾多次碰到ScrollView嵌套ListView的问题,网上的解决方法有很多种,但是杂而不全.我试过很多种方法,它们各有利弊. 在这里我将会从使用ScrollVie ...
- 解决ScrollView嵌到listView冲突问题
方法一: 把下面的方法放在绑定适配器操作的下面就行. /** * 重新计算ListView的高度,解决ScrollView和ListView两个View都有滚动的效果,在嵌套使用时起冲突的问题 * @ ...
- ListView和ScrollView冲突
当ListView放在ScrollView中的时候,无论你设置高度为 match_parent(填充父窗体)和wrap_content(包裹内容)都只显示一行,这是你把ListView放在Linear ...
随机推荐
- ASP.NET在主题中添加CSS文件
ASP.NET在主题中添加CSS文件 在ASP.NET中,可以使用CSS来控制页面上HTML元素和ASP.NET控件的皮肤.如果在主题文件夹中添加了CSS文件,则在页面应用主题时也会自动应用CSS. ...
- Java集合类之LinkedList链表
package com.test; import java.util.*; public class Demo7_3 { public static void main(String[] args) ...
- 自定义的IntentFileter 无法找到activity
<intent-filter > <action android:name="com.leo.enjoytime.VIEW"/></intent-fi ...
- 分析Java的类加载器与ClassLoader(二):classpath与查找类字节码的顺序,分析ExtClassLoader与AppClassLoader的源码
先回顾一下classpath classpath的作用: classpath的作用是指定查找类的路径:当使用java命令执行一个类(类中的main方法)时,会从classpath中进行查找这个类. 指 ...
- YII CJson类
CJson文档: http://www.yiiframework.com/doc/api/1.1/CJSON CJson::encode可以编码任何类型的数据:源码如下: public static ...
- MySQL的SQL_CALC_FOUND_ROWS
分页程序一般由两条SQL组成: SELECT COUNT(*) FROM ... WHERE .... SELECT ... FROM ... WHERE LIMIT ... 如果使用SQL_CALC ...
- 手势识别官方教程(2)识别常见手势用GestureDetector+手势回调接口/手势抽象类
简介 GestureDetector识别手势. GestureDetector.OnGestureListener是识别手势后的回调接口.GestureDetector.SimpleOnGesture ...
- UltraEdit (Ctrl + F) 查找、(Ctrl + R)替换功能失效
环境: Windows 7 Service Pack 1 X64 工具: UltraEdit Version 21 症状: UltraEdit (Ctrl + F) 查找.(Ctrl + R)替换功能 ...
- 360手机助手内部资料曝光,63张PPT纯干货
360手机助手内部资料曝光,63张PPT纯干货 日前,国内最大的安卓应用商店360手机助手发布了<2016年手机软件行业趋势绿皮书>,这份绿皮书对2015年以来移动互联网的趋势做了总结,展 ...
- bzoj1084
乍一看这题好难,根本不会: 直到看到1<=m<=2…… 显然分类讨论dp, 很快想到这题的dp和poj2430相类似 m=2的时候f[i,j,k]表示到第i行用了j个矩阵结尾状态为k时最大 ...