java.lang.Class Cast Exception: android.widget.HeaderViewListAdapter

来源:互联网 发布:js observable 编辑:程序博客网 时间:2024/05/01 17:21

如果ListView 没有 HeaderView时,BaseAdapter adapter = (BaseAdapter) lv.getAdapter() 没有错误,然而在有HeaderView 或者FooterView时,则错误。因为:




说明:

(1) “prepage”,“nextpage”等都是Button控件,“3/10”为TextView控件

(2) 将button和TextView封装在一个自定义的混合组件PageBar中

(3) 当前页面处于第一页的时候,不显示headerView,当前页面处于最后一页的时候,不显示footerView

(4) 对于显示在ListView中的数据,要保存起来,当再次浏览这一页的时候,就不用重新请求了。在Adapter中使用hashmap存储这些数据,键为页码,值为存储每页数据的List集合。


2. 实现功能

2.1 每页显示10条数据,

2.2 当点击“prepage”,“nextpage”的时候,就去请求数据,如果Adapter中已经有了这些数据,则直接从Adapter中获取,如果Adapter中没有,则去请求服务器。

2.3 请求服务器如何实现:

将所有的AsyncTask全部放在Activity中,由Activity控制这些异步任务的生命周期



3. 难点

3.1 通过解析xml的形式得到自定义组件PageBar的实例对象,但是一个ListView有一个headerView,还有一个footerView,这两个view只是显示内容不同,如果headerView和footerView使用同一个pageBar实例的话,那么控制显示内容是个很繁琐的,暂时采用实例化两个实例对象来,分别作为headerView和footerView。这里有个问题,如何得到一个实例对象的完全一样的对象,我想到了克隆,但是还没有解决这个问题,留待以后研究。

3.2 添加,移除ListView的headerView或者是footerView需要注意的地方?

添加:关于addHeaderView方法文档上有这么一句话,“Call this before calling setAdapter”,在调用这个方法之前,先要设定ListView的Adapter。addFooterView方法同样

移除:用到了系统提供的removeHeaderView或者removeFooterView方法,虽然文档上没有说明,但是调用这个方法应该在setAdapter之后。实例验证,不知道为什么,应该好好看看。


3.3 ListView上添加了headerView或者footerView的时候,在onItemClick事件里出现了问题?


private OnItemClickListener mItemClickListener = new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {JobsAdapter ad = (JobsAdapter) parent.getAdapter();ad.toggle(position);}};



报ava.lang.ClassCastException: android.widget.HeaderViewListAdapter异常?上述代码中红色的部分引起了这个异常?

首先来看看ListView的setAdapter方法:


public void setAdapter(ListAdapter adapter) {if (null != mAdapter) {mAdapter.unregisterDataSetObserver(mDataSetObserver);}resetList();mRecycler.clear();if (mHeaderViewInfos.size() > 0|| mFooterViewInfos.size() > 0) {  //红色部分mAdapter = new HeaderViewListAdapter(mHeaderViewInfos, mFooterViewInfos, adapter);  //红色代码部分} else {mAdapter = adapter;}............requestLayout();}


红色代码的意思是如果ListView没有headerView或者footerView的时候,与listView相关联的Adapter就是传进来的参数Adapter,如果有,就将原来的Adapter包装成HeaderViewListAdapter,看看HeaderViewListAdapter的文档说明:

ListAdapter used when a ListView has header views. This ListAdapter wraps another one and also keeps track of the header views and their associated data objects.

This is intended as a base class; you will probably not need to use this class directly in your own code.

HeaderViewListAdapter有个方法getWrappedAdapter,该方法能返回被包装的HeaderViewListAdapter的ListAdapter。

到了这里就明白为什么会报ClassCastException异常了。因为ListView的getAdapter方法返回的是HeaderViewListAdapter的实例,而将其转换成BaseAdapter的子类的实例,肯定是不对的。


由于ListView添加了headerView或者footerView,所以就相当于给ListView的数据添加了两项,加了个headerView,所以其他的view在界面上的位置position都增长了1,所以当用户点击界面上的第二项的时候,实际上点的是第三项,这就涉及到了ListView中的position和自定义Adapter中的position的对应关系问题了,将onItemClick改成下面的写法就好了。


private OnItemClickListener mItemClickListener = new OnItemClickListener() {@Overridepublic void onItemClick(AdapterView<?> parent, View view, int position,long id) {HeaderViewListAdapter ha = (HeaderViewListAdapter) parent.getAdapter();JobsAdapter ad = (JobsAdapter) ha.getWrappedAdapter();ad.toggle(position-1);}};





原创粉丝点击