又好久没写blog了,工作的时候,解决了一些问题,却又觉得时间紧,没空写。习惯需要坚持啊。
今天在做ListView滚动自动加载的时候碰到了Adapter Class Cast Exception Removing Footer View from ListView 问题。
感到很奇怪,怎么会出类型转换错误呢?以前用的时候怎么没碰到?我最开始在想是不是因为此时还没有给listview添加footerview。
但是这也不对啊,那样只会报Null Pointer Exception,看了一下remove的源码:
public boolean removeFooterView(View v) { if (mFooterViewInfos.size() > 0) { boolean result = false; if (mAdapter != null && ((HeaderViewListAdapter) mAdapter).removeFooter(v)) { if (mDataSetObserver != null) { mDataSetObserver.onChanged(); } result = true; } removeFixedViewInfo(v, mFooterViewInfos); return result; } return false; }
系统已经帮我判断了footerview的数量,大于0才会去remove。
于是我又开始猜想,adapter的类型转换异常难道是加了FooterView和没有加FooterView的适配器是不一样的吗?那这个adapter会在哪儿初始化呢?
应该是在listview初始化的时候,于是去打算去看看ListView的setAdapter方法:
public void setAdapter(ListAdapter adapter) {
if (mAdapter != null && mDataSetObserver != null) {
mAdapter.unregisterDataSetObserver(mDataSetObserver);
}
resetList();
mRecycler.clear();
if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}
mOldSelectedPosition = INVALID_POSITION;
mOldSelectedRowId = INVALID_ROW_ID;
// AbsListView#setAdapter will update choice mode states.
super.setAdapter(adapter);
if (mAdapter != null) {
mAreAllItemsSelectable = mAdapter.areAllItemsEnabled();
mOldItemCount = mItemCount;
mItemCount = mAdapter.getCount();
checkFocus();
mDataSetObserver = new AdapterDataSetObserver();
mAdapter.registerDataSetObserver(mDataSetObserver);
mRecycler.setViewTypeCount(mAdapter.getViewTypeCount());
int position;
if (mStackFromBottom) {
position = lookForSelectablePosition(mItemCount - 1, false);
} else {
position = lookForSelectablePosition(0, true);
}
setSelectedPositionInt(position);
setNextSelectedPositionInt(position);
if (mItemCount == 0) {
// Nothing selected
checkSelectionChanged();
}
} else {
mAreAllItemsSelectable = true;
checkFocus();
// Nothing selected
checkSelectionChanged();
}
requestLayout();
}
终于找到原因了,在HeaderView或者FooterView不为空的情况下,会把当前传入的adapter转换为HeaderViewListAdapter。否则会用原有的adapter。
So, the conclusion:
如果出现了Adapter Class Cast Exception Removing Footer View from ListView ,要在调用listview.setAdapter(myadapter);之前,加上addFooterView()或者addHeaderView()