微信公众号

Android ListView addHeaderView

最近在调试我的个人大湿说app,发现在4.2系统下直接崩溃了,看log,原来是ListView addHeaderView和setAdapter方法调用顺利不同导致的错误,这里做下记录。

正确调用

1
2
mListView.addHeaderView(mHeadView);
mListView.setAdapter(mListViewAdapter);

究其原因

Android-18(4.3)的addHeaderView源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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的源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
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版本以后做的一个处理。
以上源码分析来自:从源码上分析ListView的addHeaderView和setAdapter的调用顺序

大湿说


魅族应用市场累计下载4.4万+,我可没有做过什么推广哦,精品APP,值得下载!

二维码下载

应用市场

魅族应用市场
小米应用市场


由于多说和网易云跟帖评论服务相继关闭,来必力并不给力,因此本博客决定不再折腾评论,欢迎大家可以前往我的公众号留言交流!