listView嵌套listView的实现,以及遇到的问题的解决

来源:互联网 发布:ico图标软件下载 编辑:程序博客网 时间:2024/05/08 15:08

先看看listView嵌套listView效果图:



页面效果是ListVierw嵌套listView,外层listView(以下简称外层LV)展示的是项目,内层listView是每个项目下面对应的需求listView;效果有点类似QQ空间里的动态和其下面对应的评论。
废话不多说,看怎么实现的:
首先此fragment对应的布局文件就是一个ListView;而在listView的item的布局里,上面部分是项目标题和图片图片控件,下面又是一个自定义的ListView--解决内层LV的高度的问题(待会儿文章最后代码附上,以下简称内层LV),因为内层的LV的数据和外层的LV的数据时整体的,即内层数据是外层数据的一个jsonArray,因此,内层LV的初始化及其一系列的设置适配器和设置监听都应在外层的LV的适配器中的getView方法中实现:






外层的LV 的适配器:
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder mHolder;
//1.实例化ViewHolder
。。。。。。。。
// 2.布局填充器泵填充布局(本质上省略了xmlPullParse解析的过程)
。。。。。。。。
// 3.findViewById的过程
。。。。。。。。。
// 获取传进来的数据进行显示
// 给</span>外层item上的控件进行赋值

。。。。。。。
//注意:此处初始化内层ListView
initItemListView(convertView);
return convertView;
}
private void initItemListView(final View convertView) {
ListView definedListview = (ListView) convertView
.findViewById(R.id.expandedListview_industrychainItem);
definedListview.setAdapter(new BaseAdapter() {</span>
@Override
       public long getItemId(int position) {
      // TODO Auto-generated method stub
      return position;
}




@Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return industryChain.getIndustrychainItemDemandList().get(
position);
}


@Override
public int getCount() {
....}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolderItem mHolderItem;
//为内层LV的item的控件赋值</span>
}


OK,效果完美实现。(如果不用给内层LV的item设置点击监听的话,到此为止)


但是,
如果给内层LV的item设置点击监听的话,有个问题来了,给内层的LV 的item设置监听时,偶尔会报错,我说的是“偶尔”;报错如下:
java.lang.IllegalStateException: 
The content of the adapter has changed but ListView did not receive a notification. 
Make sure the content of your adapter is not modified from a background thread, but only from the UI thread. 
Make sure your adapter calls notifyDataSetChanged() when its content changes.

意思大体是,你的adapter的内容变化了,但是你的ListView并不知情。请保证你adapter的数据在主线程中进行更改!
怎么解决呢?内层listView的初始化,肯定是要在外层的LV 的adapter的getView中进行的,
但是要解决此问题,我们可以把获取的内层的LV 的item的数据传会给主线程,在主线程中为其赋值,问题就解决了。
方法:
如上面最开始的代码:
在外层LV 的adapter的getView方法中,替换掉调用的蓝色字体的方法,换用fragment碎片中新增定义的静态方法,同时将需要的数据传过来:
// 静态方法-初始化内层listView
// 之前是在外层listView的adapter中初始并赋值内层item的,但偶尔会报错:

/**
* java.lang.IllegalStateException: The content of the adapter has changed
* but ListView did not receive a notification. Make sure the content of
* your adapter is not modified from a background thread, but only from the
* UI thread. Make sure your adapter calls notifyDataSetChanged() when its
* content changes. [in ListView(2131034339, class
* com.bjcric.intelcce.definition.ExpandedListView) with Adapter(class
* com.bjcric.intelcce.adapter.IndustryChainListViewAdapter$2)]
*/

// 为了解决以上异常,办法:在主线程中进行赋值。
// 在外层listView的adapter中,将获取到的数据传到本主线程中

private static IndustryChainListViewItemAdapter adapter2;




void initItemListView(final Context context,
View convertView, IndustryChain industryChain) {
ListView definedListview = (ListView) convertView
.findViewById(R.id.expandedListview_industrychainItem);
adapter2 = new IndustryChainListViewItemAdapter(context, industryChain,
convertView);
definedListview.setAdapter(adapter2);




// 内层listView的item点击监听
definedListview.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Intent demandDetail = new Intent(context,
Industrychain_projectDemandDetailActivity.class);
context.startActivity(demandDetail);
}
});




}


好了,偶尔抛出的异常也已解决,listView嵌套listView的实现,和异常的解决,讲述完毕。

下面附上自定义的ListView的代码:


public class DefinedListView extends ListView {


public DefinedListView(Context context) {
super(context);
setBackgroundColor(Color.argb(100, 0, 55, 55));
}




public DefinedListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}




public DefinedListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}




@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2,
MeasureSpec.AT_MOST);




super.onMeasure(widthMeasureSpec, expandSpec);
}
}


1 0
原创粉丝点击