现在的位置: 首页 > 综合 > 正文

探秘ListView的ConvertView以及ViewHolder原理

2013年10月20日 ⁄ 综合 ⁄ 共 3718字 ⁄ 字号 评论关闭

转自:http://zhiweiofli.iteye.com/blog/1269746

最近在使用android的组件ExpandableListView,实现需求时,遇到不少奇怪的问题。

我的需求就是在ExpandableListView的父一级的view上添加两个按钮,实现添加子一级view的添加一级删除自己的功能。

 

自定义的layout如下:

 

Xml代码  收藏代码
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:id="@+id/layout_parentView"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="wrap_content" >  
  6.   
  7.     <ImageView  
  8.         android:id="@+id/iv_flag"  
  9.         android:layout_width="10dp"  
  10.         android:layout_height="10dp"  
  11.         android:layout_alignParentLeft="true"  
  12.         android:layout_centerVertical="true"  
  13.         android:layout_marginLeft="5dp"  
  14.         android:focusable="false" />  
  15.   
  16.     <TextView  
  17.         android:id="@+id/tv_typename"  
  18.         android:layout_width="100dp"  
  19.         android:layout_height="30dp"  
  20.         android:layout_centerInParent="true"  
  21.         android:layout_marginLeft="10dp"  
  22.         android:focusable="false" />  
  23.   
  24.     <ImageButton  
  25.         android:id="@+id/iv_dele"  
  26.         android:layout_width="40dp"  
  27.         android:layout_height="40dp"  
  28.         android:layout_alignParentRight="true"  
  29.         android:layout_centerVertical="true"  
  30.         android:layout_marginRight="5dp"  
  31.         android:src="@drawable/del"   
  32.         android:focusable="false"/>  
  33.   
  34.     <ImageButton  
  35.         android:id="@+id/iv_add"  
  36.         android:layout_width="40dp"  
  37.         android:layout_height="40dp"  
  38.         android:layout_marginRight="10dp"  
  39.         android:layout_toLeftOf="@id/iv_dele"  
  40.         android:src="@drawable/add"   
  41.         android:focusable="false"/>  
  42.   
  43. </RelativeLayout>  

 

GroupView部分的Java代码如下:

 

Java代码  收藏代码
  1. @Override  
  2. public View getGroupView(int groupPosition, boolean isExpanded,  
  3.         View convertView, ViewGroup parent) {  
  4.   
  5.     View parentView = null;  
  6.   
  7.     if(groupViews.size()>groupPosition){  
  8.         parentView = groupViews.get(groupPosition);  
  9.     } else {  
  10.         parentView = newParentView(groupPosition);  
  11.         groupViews.add(parentView);  
  12.     }  
  13.       
  14.     return parentView;  
  15.   
  16. }  
  17.   
  18. private View newParentView(int groupPosition){   
  19.       
  20.     View parentView = li_parent.inflate(R.layout.list_parent_view, null);  
  21.   
  22.     TextView textview = (TextView) parentView.findViewById(R.id.tv_typename);  
  23.   
  24.     BigType bt = groupList.get(groupPosition);  
  25.     textview.setText(bt.getName());  
  26.       
  27.     View v_dele = parentView.findViewById(R.id.iv_dele);  
  28.     v_dele.setTag(bt.getName());  
  29.     v_dele.setOnClickListener(new BtnDeleBigTypeListener(ct));  
  30.   
  31.     View v_add = parentView.findViewById(R.id.iv_add);  
  32.     v_add.setTag(bt.getName());  
  33.     v_add.setOnClickListener(new BtnAddSmallTypeListener(ct));  
  34.       
  35.     return parentView;  
  36. }  

 

当Activity加载该layout后,当没有展开子一级,父一级上的两个ImageButton按钮均点击正常,可是当点开子一级后,点击两个ImageButton,均得不到立即的响应 非得再产生了其他控件的点击事件(例如点击父一级,让其收起)后,之前点击 ImageButton的事件才会得到响应。一开始感觉是事件响应队列阻塞,可是为啥在产生新的事件后,所有的事件又会马上得到响应呢?

 

先做一个测试,代码见下,代码里的ViewHolder是一个自定义的类,也是后面ViewHolder模式的主要体现,这里先卖一关子...

 

Java代码  收藏代码
  1. View cache = null;  
  2.       @Override  
  3. public View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {  
  4.       
  5.     ViewHolder _vh = null;  
  6.     if(convertView == null){   
  7.         _vh = new ViewHolder();  
  8.         convertView = newParentView(_vh);  
  9.         convertView.setTag(_vh);  
  10.           
  11.         cache = convertView;  
  12.           
  13.     } else {  
  14.         _vh = (ViewHolder) convertView.getTag();  
  15.           
  16.         if(cache.equals(convertView)){  
  17.             Log.i(TAG, "equals old obj");  
  18.         }  
  19.     }  
  20.       
  21.     return convertView;  
  22.   
  23. }  

  上面代码主要就是想测试converView,究竟是拿来干什么的,google文档里头做了如此解析:


大致意思就是在重复利用此物之前要检查其是否为null!可是就没说清楚,这个convertView究竟是什么时候会存在!

 

现在来看看测试的结果,ExpandableListView总共有4个父节点,但是有以下三次输出结果:


抱歉!评论已关闭.