• 从源代码上分析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吧。

  • 相关阅读:
    WMI系统管理工具介绍和获取机器码
    QListWidget高性能加载图片数据
    2.5偏差方差分解
    QT图片旋转动画
    Qt实现数字滚动动画效果
    Qt动画使用总结
    线性回归--经验最小化,结构最小化,最大似然估计,最大后验估计
    获取国家2019年最新的省、市、区/县、街道、小区/居委会信息 包括港澳台
    .net 利用Emit将object转为DbParameter,DataTable转为List<>
    c#简单操作MongoDB_2.4
  • 原文地址:https://www.cnblogs.com/mfrbuaa/p/4307119.html
Copyright © 2020-2023  润新知