ListView想要添加headerview的话,就要通过addHeaderView这个方法,然后想要为ListView设置数据的话,就要调用setAdapter方法了。但是,在调用addHeaderView和setAdapter的顺序上,有时会爆出Java.lang.IllegalStateException: Cannot add header view to list -- setAdapter has already been called.的异常。这是因为我们在addHeaderView之前调用了setAdapter。所以,在这里,建议setAdapter需要在addHeaderView和addfooterView之后调用。这样就安全了。下面,我们来看看源码吧。看看究竟是什么原因造成的。

Android-18(4.3)的addHeaderView源码:

public void addHeaderView(View v, Object data, boolean isSelectable) {  
        final FixedViewInfo info = new FixedViewInfo();  
        info.view = v;  
        info.data = data;  
        info.isSelectable = isSelectable;  
        mHeaderViewInfos.add(info);  
   
        // Wrap the adapter if it wasn't already wrapped.  
        if (mAdapter != null) {  
            if (!(mAdapter instanceof HeaderViewListAdapter)) {  
                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);  
            }  
   
            // In the case of re-adding a header view, or adding one later on,  
            // we need to notify the observer.  
            if (mDataSetObserver != null) {  
                mDataSetObserver.onChanged();  
            }  
        }  
}  

Android-17(4.2)的addHeaderView的源码:

public void addHeaderView(View v, Object data, boolean isSelectable) {  
   
        if (mAdapter != null && ! (mAdapter instanceof HeaderViewListAdapter)) {  
            throw new IllegalStateException(  
                    "Cannot add header view to list -- setAdapter has already been called.");  
        }  
   
        FixedViewInfo info = new FixedViewInfo();  
        info.view = v;  
        info.data = data;  
        info.isSelectable = isSelectable;  
        mHeaderViewInfos.add(info);  
   
        // in the case of re-adding a header view, or adding one later on,  
        // we need to notify the observer  
        if (mAdapter != null && mDataSetObserver != null) {  
            mDataSetObserver.onChanged();  
        }  
}  

  

  在上面,我们可以对比出代码中的处理的不同。在17版本中,只要adapter不为空的话,那就直接会抛出异常,而这个异常恰好就是我们文章开头说到的异常。在18版本中,如果adapter不为空的话,则会新建一个adapter,这个adapter会包含了headerview和footerview以及我们传进来的原来的adapter。这是在18版本以后做的一个处理。虽然有了处理,但是建议大家还是按照上面说的调用顺序来使用addHeaderView,addFooterView和setAdapter吧。

从源码上分析ListView的addHeaderView和setAdapter的调用顺序的更多相关文章

  1. 从源代码上分析ListView的addHeaderView和setAdapter的调用顺序

    ListView想要加入headerview的话,就要通过addHeaderView这种方法,然后想要为ListView设置数据的话,就要调用setAdapter方法了.可是,在调用addHeader ...

  2. 硬核干货:4W字从源码上分析JUC线程池ThreadPoolExecutor的实现原理

    前提 很早之前就打算看一次JUC线程池ThreadPoolExecutor的源码实现,由于近段时间比较忙,一直没有时间整理出源码分析的文章.之前在分析扩展线程池实现可回调的Future时候曾经提到并发 ...

  3. 【转】从源码来分析ListView

    原文:http://yanmingming.sinaapp.com/?p=1251 原文其实不叫这个名字,本文对于原文有一定的修改,觉得这个名字比较适合本篇. 一.ListView 的工作原理 Ada ...

  4. Android addHeaderView和setAdapter的调用顺序后报错

    在4.4之前的系统,setAdapter后再设置addHeaderView会爆 ListView想要添加headerview的话,就要通过addHeaderView这个方法,然后想要为ListView ...

  5. JUC同步器框架AbstractQueuedSynchronizer源码图文分析

    JUC同步器框架AbstractQueuedSynchronizer源码图文分析 前提 Doug Lea大神在编写JUC(java.util.concurrent)包的时候引入了java.util.c ...

  6. 自定义View系列教程02--onMeasure源码详尽分析

    深入探讨Android异步精髓Handler 站在源码的肩膀上全解Scroller工作机制 Android多分辨率适配框架(1)- 核心基础 Android多分辨率适配框架(2)- 原理剖析 Andr ...

  7. MapReduce的ReduceTask任务的运行源码级分析

    MapReduce的MapTask任务的运行源码级分析 这篇文章好不容易恢复了...谢天谢地...这篇文章讲了MapTask的执行流程.咱们这一节讲解ReduceTask的执行流程.ReduceTas ...

  8. MapReduce的MapTask任务的运行源码级分析

    TaskTracker任务初始化及启动task源码级分析 这篇文章中分析了任务的启动,每个task都会使用一个进程占用一个JVM来执行,org.apache.hadoop.mapred.Child方法 ...

  9. TaskTracker任务初始化及启动task源码级分析

    在监听器初始化Job.JobTracker相应TaskTracker心跳.调度器分配task源码级分析中我们分析的Tasktracker发送心跳的机制,这一节我们分析TaskTracker接受JobT ...

随机推荐

  1. string的七种用法

    以下是string的七种用法,注意哦,记得要时常去查看java的API文档,那个里面也有很详细的介绍 1>获取 1.1:字符串中包含的字符数,也就是字符串的长度.  int length():获 ...

  2. (转)CentOS 7 单用户模式+救援模式

    原文:http://blog.51cto.com/asd9577/1931442 https://www.cnblogs.com/zhangzeyu/p/6379754.html-------Cent ...

  3. 细说Activity与Task(任务栈)

    Task概要: task是一个具有栈结构的容器,可以放置多个Activity实例.启动一个应用,系统就会为之创建一个task,来放置根Activity:默认情况下, 一个Activity启动另一个Ac ...

  4. Zookeeper在Centos7上搭建单节点应用

    (默认机器上已经安装并配置好了jdk) 1.下载zookeeper并解压 $ tar -zxvf zookeeper-3.4.6.tar.gz 2.将解压后的文件夹移动到 /usr/local/ 目录 ...

  5. 【转】Entity framework 6 编写的通用数据类

    原文:http://blog.csdn.net/laokaizzz/article/details/25730813 准备参考

  6. Cocos2d-x游戏导出android工程,提取cocos的so文件

      Cocos2d-x游戏导出android工程,提取cocos的so文件   原本cocos游戏的android工程编译时,需要将cocos的库文件进行编译,这些文件大部分是cpp文件, 使用ndk ...

  7. java序列化测试

    0.前言 本文主要对几种常见Java序列化方式进行实现.包括Java原生以流的方法进行的序列化.Json序列化.FastJson序列化.Protobuff序列化. 1.Java原生序列化 Java原生 ...

  8. C++11中右值引用和移动语义

    目录 左值.右值.左值引用.右值引用 右值引用和统一引用 使用右值引用,避免深拷贝,优化程序性能 std::move()移动语义 std::forward()完美转发 容器中的emplace_back ...

  9. 2013年8月12日Python的5个最有价值问题

    问:Python怎么在字典里删除值但保留相应的键 答: 假设3都在值里,而非键>>> for v in D1.values():...     if 3 in v:...       ...

  10. [转] Lodop、C-Lodop使用说明及样例

    本文转自:http://www.lodop.net/LodopDemo.html Lodop(标音:劳道谱,俗称:露肚皮)是专业WEB控件,用它既可裁剪输出页面内容,又可用程序代码直接实现 复杂打印. ...