ListView中ConvertView和ViewHolder

1、概述

[java] view plain copy
  1. ListView是Android中非常常见的控件通过Adapter架起数据与界面显示的桥梁,MVC思想在其中得到了很好地体现:  

M:model 数据模型    添加到ListView中显示的数据

V:View   视图 在界面中显示的每一条样式(不只是通常的每一条,比如QQ聊天间隔显示的样式)

C:Control  控制  通过Activity来协调全局

其中的关键所在就是Adapter(适配器),它就是一座桥梁,Adapter提供对数据的访问,也负责为每个数据产生每个对应的View,产生View之后然后将View添加到ListView之中,如何优雅的使用ListView请往下移步

ListView中ConvertView和ViewHolder



2、ConvertView和ViewHolder

当每条数据进入Adapter时,adapter就要开始调用其 getView(int position, View convertView, ViewGroup parent)方法,以最简单的item为例:每个item仅包含一个图片(imageView)和一行文本(textView)


2.1、最原始的方法(不实用容易导致内存泄露)

非常不推荐这样用,毫不优雅毫无美感!!!

[java] view plain copy
  1. public void getView(int position , View convertView , ViewGroup parent){  
  2.         View item = mInflater.inflate(R.layout.list_view, null);  
  3.         (TextView)item.findViewById(R.id.text).setText(DATA[position]);  
  4.         (ImageView)item.findViewById(R.id.img).setImageBitmap(icon);  
  5.         return item;  
  6.     }  


2.2 使用 ConVertView回收视图(看看就好,小数据量可以使用)

[java] view plain copy
  1. public void getView(int position , View convertView , ViewGroup parent){  
  2.         if(convertView == null){  
  3.             convertView = mInflater.inflate(R.layout.list_view, null);  
  4.         }  
  5.       (TextView)convertView.findViewById(R.id.text).setText(DATA[position]);  
  6.   
  7.       (ImageView)convertView.findViewById(R.id.img).setImageBitmap(icon);  
  8.   
  9.          return convertView;  
  10.     }  

这里提到了“回收”,在Android中提供了一种叫做Recycler(反复循环器)的构件

【原理】就是 当ListView的Item从屏幕上方滚出视线之外后(下图Item1),对应的Item的View会被缓存到Recycler中,相应的会从屏幕下方生成一个新的Item(对应下图的Item8),此时调用的getView中的conView中就是已经被缓存的(item1),不用再创建新的视图上面的代码就是重用了这个convertView改善了listview的性能。

ListView中ConvertView和ViewHolder


总之,初始时ListView会从Adapter中根据当前的屏幕布局实例化一定数量的view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list item的view对象会被回收,然后被用来构造新出现的最下面的list item。这个构造过程就是由getView()方法完成的,getView()的第二个形参 View convertView就是被缓存起来的list item的view对象(初始化时缓存中没有view对象则convertView是null)。由此可以看出,如果我们不去使用convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。

2.3 convertView+ViewHolder(大量数据加载时常用)

先上代码

[java] view plain copy
  1. static class ViewHolder{  
  2.         private TextView tv;  
  3.         private ImageView iv;  
  4.     }  
  5.       
  6.     public void getView(int position , View convertView , ViewGroup parent){  
  7.         ViewHolder holder;  
  8.         if(convertView == null){  
  9.             convertView = mInflater.inflate(R.layout.list_view, null);  
  10.             holder = new ViewHolder();  
  11.             holder.tv = (TextView)convertView.findViewById(R.id.text);  
  12.             holder.iv = (ImageView)convertView.findViewById(R.id.img);  
  13.             convertView.setTag(holder);  
  14.         }else{  
  15.             holder = (ViewHolder) convertView.getTag();  
  16.         }  
  17.         holder.tv.setText(DATA[position]);  
  18.         holder.iv.setImageBitmap(icon);  
  19.         return convertView;  
  20.     }  


这种方式使用到了ViewHolder,其实ViewHolder就是一个很普通的类,类似一个Bean,用来将混存的View封装好,convertView中的SetTag将这些缓存打上对应的标签以供下次直接打包调用,大大提高了速度,特别是在ListView布局多样化时ViewHolder作用就更加明显了。

3、其他

【1】隐藏ListView的滚动条

Android:srcollbar=“none”

【2】取消ListView的点击效果

android:listSelector = “#00000000”或者使用android自带的透明效果android:listSelector = “@android:color/transparent”

(不然点击就会出现很难看的黄色背景色。)

【3】设置条目分割线

android:divider="@android:color/darker_gray"

android:dividerHeight = "10dp"


转载:http://blog.****.net/xsf50717/article/details/49206385