您的位置:首页 > 编程语言 > Java开发

ListView在removeFooterView时报java.lang.ClassCastException错问题

2015-09-23 19:51 441 查看
自古英雄不问出处,奈何我却不是英雄!

转载请标明出处:http://blog.csdn.net/u011275767/article/details/48679231
本文出自:【陈传恒的博客】
这些天遇到一个很奇怪的问题,很奇怪的问题,很奇怪的问题。重要的事情要说三遍。奇怪的问题大都是在解决之间很奇怪,如果你解决之后你会发现奇怪的是你自己。下面我来说一下我是怎么奇怪了一把的。
这个奇怪的问题(其实不奇怪)是跟ListView有关系。先说问题和解决办法:java.lang.Class Cast Exception: android.widget.HeaderViewListAdapter这么一个异常。那么你就要看看你的listView.addFooterView是不是放在了listView.setAdaptr后面了。咋办呢,把它放前面就好了。
下面来说说出问题的愿意,这里有一个HeaderViewListAdapter,首先你回想:这是什么鬼。没见过这个类,哪里来的转换异常。下面咱们看一下源码:

@Override
public void setAdapter(ListAdapter adapter) {

if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {
mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);
} else {
mAdapter = adapter;
}

}
这段代码是listView中的源码,源代码有很多行,不过咱们不用看,就这一段就可以。有木有发现HeaderViewListAdapter这个鬼。这里的if判断中的mHeaderViewInfos和mFooterViewInfos就是咱们加的listView的header和footer。至于.size()这个方法,咱们暂且理解为你是否为listView add过header或者footer。稍后再来详细说明一下。想必大家能够理解了,如果你设置了header或者footer中的其中一个,就会New出一个HeaderViewListAdapter,然后传入三个参数分别是header和footer和你传入的adapter。没设置的话就直接是你创建的那个adapter了。下面看这段源代码:

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;
}
看到没有。listView调用的的时候是HeaderViewListAdapter来执行的,由于你没有先设置header或者footer,导致adapter还是原来的,并不是HeaderViewListAdapter。结果就会出现咱们遇到的类转换异常了。

-------------------这里是分割线,下面的已经和问题无关,这里只做拓展----------------------

下面再来说一下上面提到的mHeaderViewInfos.size()和mFooterViewInfos.size()。这里只是来说明为什么是.size(),而不是用是否为null来判断,咱们还是来看源码:
/**
* A class that represents a fixed view in a list, for example a header at the top
* or a footer at the bottom.
*/
public class FixedViewInfo {
/** The view to add to the list */
public View view;
/** The data backing the view. This is returned from {@link ListAdapter#getItem(int)}. */
public Object data;
/** <code>true</code> if the fixed view should be selectable in the list */
public boolean isSelectable;
}
private ArrayList<FixedViewInfo> mHeaderViewInfos = Lists.newArrayList();
private ArrayList<FixedViewInfo> mFooterViewInfos = Lists.newArrayList();

看到了吧,这里是new出来的,咋能用null判断呢。
再来往下看addHeaderView和addFooterView之后,会走源码中的下面这两个方法:

public void addHeaderView(View v) {
addHeaderView(v, null, true);
}
public void addFooterView(View v) {
addFooterView(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);
// 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();
}
}
}
由于addFooterView和addHeaderView非常类似,这里我就补贴代码了。咱们主要来说明这三个参数是什么。

第一个参数:View
v,我就不多说了,就是咱们传进来的View。
第二个参数:Object
data,这个就是你header中的数据,你传入之后在点击header的时候可以用getItem(int)这个方法获取出来。当然也是可以不传的,咱们是可以通过别的方法做出和点击同样效果的,我就不说了,大家都懂得。
第三个参数:boolean
isSelectabe,简单来说,就是为了让header或者footer可不可点的,true就是能点击,索引就是0。false就是不能点击了

------------------这里是分割线,拓展结束------------------

好了就这么多。希望对大家有用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: