java.lang.IllegalStateException:Cannot add header view to list==setAdapter has already been called.

只要先addHeadView再setAdapter即可解决。
下面简单探究一下

Demo实例

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ListView lv = new ListView(this);
        setContentView(lv);
//        TextView headView = new TextView(this);
//        headView.setText("headView");
//        lv.addHeaderView(headView);
        List<String> dataList = new ArrayList<String>();
        for (int j = 0; j < 30; j++) {
            dataList.add("" + j);
        }
        ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(
                this, android.R.layout.simple_list_item_1,
                dataList);
        lv.setAdapter(arrayAdapter);
        TextView headView = new TextView(this);
        headView.setText("headView");
        lv.addHeaderView(headView);
    }

}

这里写图片描述
修改代码,只要在setAdapter之前addHeaderView就ok了。

源码分析

注意这里要使用低版本的sdk的源代码进行分析(这里使用Android4.0)

  public void addHeaderView(View v) {
        addHeaderView(v, null, true);
    }
      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.");
        }
        ...

HeaderViewListAdapter这是怎么来的呢?让咱们看一下setAdapter

   @Override
    public void setAdapter(ListAdapter adapter) {
      ...
        if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
            mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
            ...

mHeaderViewInfos是什么?和headView有关系?让咱们继续看一下addHeadView

  public void addHeaderView(View v) {
        addHeaderView(v, null, true);
    }
  public void addHeaderView(View v, Object data, boolean isSelectable) {

     ...
        FixedViewInfo info = new FixedViewInfo();
        info.view = v;
        info.data = data;
        info.isSelectable = isSelectable;
        mHeaderViewInfos.add(info);

    ...

看到了mHeaderViewInfos包含了headView的容器的列表,mHeaderViewInfos反应了ListView中headView的信息。

所以:在低版本sdk中,从代码级别就限制ListView必须要先addHeadView,然后setAdapter.

让咱们看一下高版本的情况吧(这里使用Android6.0)

  public void addHeaderView(View v) {
        addHeaderView(v, null, true);
    }
      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);
        mAreAllItemsSelectable &= isSelectable;

        // Wrap the adapter if it wasn't already wrapped.
        if (mAdapter != null) {
            if (!(mAdapter instanceof HeaderViewListAdapter)) {
                mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, mAdapter);
            }
            ...

版本升级了,的确是更好了!
为了兼容低版本,我们依然要首先addHeadView,然后setAdapter.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值