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

  • 相关阅读:
    条件概率-独立事件-互斥事件-对立事件
    数学
    可视化:svg相关基础
    移动端调用摄像头(相机)相册
    移动端的事件点透及原因
    ios滑动流畅(丝般顺滑)滚动
    动画框架基础部分
    css美化select标签,兼容ie10 ie10+,chrome。但不支持ie9 ie9-
    ie11 调试工具不能使用
    css使用
  • 原文地址:https://www.cnblogs.com/ganchuanpu/p/6666181.html
Copyright © 2011-2022 走看看