您的位置:首页 > 移动开发 > Android开发

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

2016-12-08 13:17 447 查看

问题重现:

在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做了调整。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android listview 兼容
相关文章推荐