前言

  在开发Android应用过程中经常要与列表展示打交道,比如Listview。在使用过程中如果不能正确的进行细节处理那么对性能还是有很大的损耗的。

  Listview展示内容是通过一个Adapter来进行内容绑定的。如下所示:

  

 class Adapter implements ListAdapter{

         @Override
public void registerDataSetObserver(DataSetObserver observer) { } @Override
public void unregisterDataSetObserver(DataSetObserver observer) { } @Override
public int getCount() {
return items.size();
} @Override
public Object getItem(int position) {
return items.get(position);
} @Override
public long getItemId(int position) {
return position;
} @Override
public boolean hasStableIds() {
return false;
} @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh =null;
if(convertView==null){
vh = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);
vh.tv = (TextView) convertView.findViewById(R.id.tvShow); convertView.setTag(vh);
}else{
vh = (ViewHolder) convertView.getTag();
} vh.tv.setText(items.get(position)); return convertView;
} @Override
public int getItemViewType(int position) {
return 1;
} @Override
public int getViewTypeCount() {
return 1;
} @Override
public boolean isEmpty() {
return false;
} @Override
public boolean areAllItemsEnabled() {
return false;
} @Override
public boolean isEnabled(int position) {
return true;
} }

  有了这个Adapter就可以与Listview进行数据绑定了,如下所示:

  

lv.setAdapter(new Adapter());

  

getViw

在Adapter类中有一个重要的实现方法getView用来实现大部分的逻辑,这个就是这篇文章的重点。

public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder vh =null;
if(convertView==null){
vh = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);
vh.tv = (TextView) convertView.findViewById(R.id.tvShow); convertView.setTag(vh);
}else{
vh = (ViewHolder) convertView.getTag();
} vh.tv.setText(items.get(position)); return convertView;
}

  先看下这个方法的官方解释

  Get a View that displays the data at the specified position in the data set.
  You can either create a View manually or inflate it from an XML layout file.

  意思是说:获取一个用来展示数据集中指定位置的数据的视图。可以通过代码或者inflate一个XML文件来获得这个View对象。

  Parameters(参数)
      position

      The position of the item within the adapter's data set of the item whose view we want.

      我们要展示的数据集中的数据条目的位置
      convertView
          The old view to reuse, if possible. Note: You should check that this view is non-null and of an appropriate type before using.
          If it is not possible to convert this view to display the correct data, this method can create a new view.
     Heterogeneous lists can specify their number of view types, so that this View is always of the right type (see getViewTypeCount()and       getItemViewType(int)).

      一个能用就用的旧视图。注意:在使用之前你需要去检查这个视图是否非空以及其类型。

      如果这个视图不能用来正确展示数据,那么此方法就需要创建一个新的视图了。

      如果一个列表中有多种视图类型,那么也可以通过getViewTypeCount\getItemViewType方法来正确使用。
      parent     
          The parent that this view will eventually be attached to

      这个视图要被添加到的对象

convertView

  上一段提到了convertView的reuse(重利用)的内容,也就是说在创建一个新视图去返回给List 的时候需要先检查下旧的视图对象是否还可以利用,包括去检查是否为空以及类型是否正确等等。当然大部分情况下是可以利用的,因此通过这种方式就降低了每次去创建一个item 的view的性能开销了

  view能够重复利用了,那么view中的对象是不是也能够重利用呢,比如其中的展示文本。当然,这就是这篇文章的标题提到的ViewHolder。

ViewHolder

  从字面上理解ViewHolder,a holder of the view,就是一个视图的持有者,持有的内容就是视图的所有指定内容,或者说是绑定内容(下面会提到绑定)。个人理解这个持有的意思,就好比是一个引用或者一个指针,ViewHolder中的内容发生了变化那么对应的view中也会随之发生变化;view中的内容发生了变化那么ViewHolder中也随之发生了变化。这就是所谓的hold吧。下面就看下如果绑定一个ViewHolder。

  先要定义一个ViewHolder对象,对象里面的内容就是需要hold的视图的内容,比如List中每一个item就是一个TextView用来展示信息,那么如下所示:

static final class ViewHolder{
TextView tv;
}

  Item对象的XML,如下:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="20dip" > <TextView
android:layout_marginTop="5dip"
android:layout_marginBottom="5dip"
android:id="@+id/tvShow"
android:layout_width="wrap_content"
android:layout_height="wrap_content" /> </LinearLayout>

  ViewHolder中的tv就是用来hold  Item找那个的tvShow的。

  ViewHolder有了,那么下面就进入绑定过程。还是回过头来看下getView那个方法片段。

  

vh = new ViewHolder();
convertView = mInflater.inflate(R.layout.item, null);
vh.tv = (TextView) convertView.findViewById(R.id.tvShow); convertView.setTag(vh);

  先把ViewHolder和convertView两个对象建出来,然后通过vh.tv = (TextView) convertView.findViewById(R.id.tvShow);进行了绑定,这样他们之间就产生了关联。

  最后通过convertView.setTag(vh);方法使得View和ViewHolder产生了关联,也就是vh真正成为了convertView这个View的holder。

  通过这样的方式,以后如果重利用这个视图,就可以通过vh = (ViewHolder) convertView.getTag();的方法来吧这个Holder拿出来,修改其中的内容就可以通过下面的方式了vh.tv.setText(items.get(position));

  这样的话省去了findViwyById这样的查找,降低了开销

后记:

  Listview有很多中优化性能的方式,这个算是其中一种。

完整代码:ViewHolderDemo

原文连接:http://www.cnblogs.com/luoaz/p/3734999.html

  

Android:ListView之ViewHolder的更多相关文章

  1. 【腾讯Bugly干货分享】Android ListView与RecyclerView对比浅析--缓存机制

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/5811d3e3ab10c62013697408 作者:黄宁源 一,背景 Recy ...

  2. Android ListView 常用技巧

    Android ListView 常用技巧 Android TextView 常用技巧 1.使用ViewHolder提高效率 ViewHolder模式充分利用了ListView的视图缓存机制,避免了每 ...

  3. Android ListView添加多种类型的ItemView

    一般复杂的ListView都会重写BaseAdapter,通过重用convertView来减少inflate,通过setTag()和ViewHolder改变ItemView的内容. 重写BaseAda ...

  4. Android ListView滑动过程中图片显示重复错乱闪烁问题解决

    最新内容建议直接访问原文:Android ListView滑动过程中图片显示重复错乱闪烁问题解决 主要分析Android ListView滚动过程中图片显示重复.错乱.闪烁的原因及解决方法,顺带提及L ...

  5. Android ListView(Selector 背景图片 全选 Checkbox等按钮)

    list_item.xml <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xm ...

  6. Android listview 的优化

    接[Android listview的应用][1] 在我们上一篇[Android listview的应用][1]中,我们的adapter中的getView()方法中每次都将布局重新加载一遍,这样就会导 ...

  7. android listview需要呈现多个布局

    android listview需要呈现多个布局 之前的做法很笨 在getView()方法里面,不仅将viewHolder作为tag属性设置给convertView 还将当前的position作为ta ...

  8. android ListView优化

    android ListView通过优化重用历史缓存实现.listview相应的数据适配器一般使用自己定义BaseAdapter子类,重用历史缓冲区来提高性能. 例如,下面的示例代码演示: 1.lis ...

  9. [置顶] android ListView包含Checkbox滑动时状态改变

    题外话: 在xamarin android的开发中基本上所有人都会遇到这个小小的坎,的确有点麻烦,当时我也折腾了好一半天,如果你能看到这篇博客,说明你和我当初也是一样的焦灼,如果你想解决掉这个小小的坎 ...

随机推荐

  1. [改善Java代码]用枚举实现工厂方法模式更简洁

    工厂方法模式(Factory Method Patter)是"创建对象的接口",让子类决定实例化哪一个类,并使一个类的实例化延迟到其子类.工厂方法模式在我们的开发工作中,经常会用到 ...

  2. 并查集(UVA 1106)

    POINT: 把每个元素看成顶点,则一个简单化合物就是一条无向边,若存在环(即k对组合中有k种元素),则危险,不应该装箱,反之,装箱: 用一个并查集维护连通分量集合,每次得到一种化合物(x, y)时检 ...

  3. Spring AOP原理解析

    原文链接请参见:http://blog.csdn.net/u010723709/article/details/47839307

  4. Codeforces Round #191 (Div. 2)

    在div 188中,幸运的达成了这学期的一个目标:CF1800+,所以这次可以打星去做div2,有点爽. A.Flipping Game 直接枚举 B. Hungry Sequence 由于素数的分布 ...

  5. 【解决】应用程序无法正常启动(0xc000007b)。请单击“确定”关闭应用程序。

    换了SSD硬盘,装了Windows 7 SP1 x64的系统.用了一段时间,突然一天有些软件打不开了.弹出下面的提示 应用程序无法正常启动(0xc000007b).请单击“确定”关闭应用程序.第一时间 ...

  6. 使用C#动态生成Word文档/Excel文档的程序测试通过后,部署到IIS服务器上,不能正常使用的问题解决方案

    使用C#动态生成Word文档/Excel文档的程序功能调试.测试通过后,部署到服务器上,不能正常使用的问题解决方案: 原因: 可能asp.net程序或iis访问excel组件时权限不够(Ps:Syst ...

  7. Jersey(1.19.1) - Extracting Request Parameters

    Parameters of a resource method may be annotated with parameter-based annotations to extract informa ...

  8. Redis 命令 - Transactions

    DISCARD Discard all commands issued after MULTI 127.0.0.1:6379> MGET bank:A:account bank:B:accoun ...

  9. Git CMD - rm: Remove files from the working tree and from the index

    命令格式 git rm [-f | --force] [-n] [-r] [--cached] [--ignore-unmatch] [--quiet] [--] <file>…​ 命令参 ...

  10. .net System.Net.Mail 之用SmtpClient发送邮件 Demo

    private static bool sendMail() { try { //接收人邮箱 string SendTo = "XXXXX@163.com"; //抄送人邮箱 st ...