zoukankan      html  css  js  c++  java
  • 从源代码上分析ListView的addHeaderView和setAdapter的调用顺序

    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吧。

  • 相关阅读:
    LDAP2-创建OU创建用户
    GNE: 4行代码实现新闻类网站通用爬虫
    为什么每一个爬虫工程师都应该学习 Kafka
    新闻网页通用抽取器GNEv0.04版更新,支持提取正文图片与源代码
    写了那么久的Python,你应该学会使用yield关键字了
    新闻类网页正文通用抽取器
    为什么Python 3.6以后字典有序并且效率更高?
    为什么你需要少看垃圾博客以及如何在Python里精确地四舍五入
    数据工程师妹子养成手记——数据库篇
    一行js代码识别Selenium+Webdriver及其应对方案
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4307119.html
Copyright © 2011-2022 走看看