Android 4.4以下ListView addHeader和addFooter放在setAdapter之后导致异常的原因分析和解决

来源:互联网 发布:编程需要哪些基础知识 编辑:程序博客网 时间:2024/06/05 06:15

问题重现:

在Android 19之前,ListView的addHeader和addFooter必须在setAdapter之前调用,否则就会有异常,Android 19以及之后是没有这个问题的。异常的具体表现为:
1.在setAdapter之后调用mListView.addHeaderView(mHeader);会抛出异常:
Cannot add header view to list -- setAdapter has already been called.
2.在setAdapter之后调用mListView.addFooterView(mFooter);虽然不会抛出异常,但是却看不到添加的footer。

问题解决:

在Android 19之前,如果想在setAdapter之后添加header和footer,可以这样做:

//设置adapter之后设置header和footer        ListAdapter originalAdapter; //得到之前给listview设置的adapter,如果已经知道,可以不用        if (mListView.getAdapter() instanceof HeaderViewListAdapter) {            HeaderViewListAdapter headerViewListAdapter = (HeaderViewListAdapter) mListView.getAdapter();            originalAdapter = headerViewListAdapter.getWrappedAdapter();        } else {            originalAdapter = mListView.getAdapter();        }        mListView.setAdapter(null);        mListView.addHeaderView(mHeader);        mListView.addFooterView(mFooter);        mListView.setAdapter(originalAdapter);

问题原因

我们可以对比Android 18和19的ListView的源码,在addHeaderView的改变:

  • API 18
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();    }}
  • API 19
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 19之前,如果ListView设置过Adapter,会抛出异常,在Android 19中,google做了调整。

0 0
原创粉丝点击