今天在使用ListView 的 addFooterView 的方法时候,遇到了一个问题。当我代码中执行了如下的操作

ListView listView = new ListView(this);
listView.addFooterView(mItem);
listview.setAdapter(mAdapter);
listview.getAdapter();

得到的adapter一直报错,说是类转化错误。后来通过看ListView源码发现了问题所在。

我们看一下addFooterView方法

 public void addFooterView(View v, Object data, boolean isSelectable) {
final FixedViewInfo info = new FixedViewInfo();
info.view = v;
info.data = data;
info.isSelectable = isSelectable;
mFooterViewInfos.add(info);
mAreAllItemsSelectable &= isSelectable; // 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 footer view, or adding one later on,
// we need to notify the observer.
if (mDataSetObserver != null) {
mDataSetObserver.onChanged();
}
}
}

我们看到当我们使用这个方法的时候,其他会把adapter重新创建成为HeaderViewListAdapter,当我们再次得到adapter的时候,它其实已经不是你set 进去的adapter了

网上有好多人说,我们只需要在listview.setAdapter()方法之前使用addFooter方法就可以避免这个问题。我尝试了这种方法,结果还是一样的结果。也就是说,无论你在setAdapter()前后使用这个方法

,对adapter的影响都是一样的,因为我们通过看ListView的setAdapter方法就知道原因了

        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}

我们看到setAdapter里面有上面这句代码。这就说明了,我们无论在哪里使用addFooter方法,其实都会更改adapter

现在我们可以在看看,HeaderViewListAdapter是一个什么东西

public class HeaderViewListAdapter implements WrapperListAdapter, Filterable {

    private final ListAdapter mAdapter;

    // These two ArrayList are assumed to NOT be null.
// They are indeed created when declared in ListView and then shared.
ArrayList<ListView.FixedViewInfo> mHeaderViewInfos;
ArrayList<ListView.FixedViewInfo> mFooterViewInfos;
。。。。。。。。。。。。。。。。

它其实也是一个adapter,只不过它里面保存了listview的adapter跟head、foot信息。这样,如果我们想得到当初我们赋给listview的adapter的话,可以考虑从它里面得到。

另外一点需要注意,当我们通过listview.getAdapter()得到adapter的时候,然后通过adapter.getCount的方法得到的item数,是包含了head跟foot的。看下HeaderViewListAdapter 中

getcount方法

    public int getCount() {
if (mAdapter != null) {
return getFootersCount() + getHeadersCount() + mAdapter.getCount();
} else {
return getFootersCount() + getHeadersCount();
}
}

如果我们想要使用listview.getAdapter()得到我们当初传入的纯净adapter,可以使用如下方法

                    Adapter a =  listView.getAdapter();
ConversationListAdapter adapter = null;
if (a instanceof HeaderViewListAdapter) {
adapter = (ConversationListAdapter) ((HeaderViewListAdapter) a).getWrappedAdapter();
} else if (a instanceof ConversationListAdapter) {
adapter = (ConversationListAdapter) a;
} else {
android.util.Log.e("zhangshuli", "a=="+a);
}

也就是通过instanceof方法,判断我们得到的adapter是原来的,还是被listview改造过的。其中getWrappedAdapter是HeaderViewListAdapter提供的方法,获得的就是纯净adapter

最新文章

  1. 自定义鼠标光标cursor
  2. java执行linux命令
  3. MFC绘制图片闪烁详解
  4. PowerDesigner怎样才能在修改表的字段Name的时候Code不自动跟着变
  5. 关于学习session的一二
  6. Rsync 3.1.0 发布,文件同步工具
  7. 神奇的NOIP模拟赛 T1 LGTB 玩扫雷
  8. struts.properties的参数描述
  9. 【Unity入门】场景编辑与场景漫游快捷键
  10. &lt;一&gt;初探js特效魅力之全选不选反选04
  11. Saiku对Measure(指标)查询结果进行计算后显示的方法
  12. 虚拟键盘冲击移动端fixed布局的解决方案
  13. Android中帧动画的创建
  14. XSS攻击原理及防御措施
  15. MATLAB cftool工具数据拟合结果好坏判断
  16. three.js学习:纹理Texture之平面纹理
  17. MyBatis对入参对象的属性空判断
  18. linux centos挂载数据盘教程
  19. 并发编程—— LinkedTransferQueue
  20. 15_常用API_第15天(Object、String、StringBuffer、用户登陆注册)_讲义

热门文章

  1. hive安装用mysql作为元数据库,mysql的设置
  2. 安卓开发--AsyncTask
  3. SharePoint InfoPath 保存无法发布问题
  4. &lt;Sicily&gt;Inversion Number(线段树求逆序数)
  5. ES6中常用的简写方式
  6. php--防止DDos攻击代码
  7. UI Framework-1: Native Controls
  8. caffe(10) 命令行解析
  9. 监控memcached服务
  10. Unity Shader (四)顶点程序示例