Android:ListView之ViewHolder

前言


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

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

  


 1 class Adapter implements ListAdapter{
2
3 @Override
4 public void registerDataSetObserver(DataSetObserver observer) {
5
6 }
7
8 @Override
9 public void unregisterDataSetObserver(DataSetObserver observer) {
10
11 }
12
13 @Override
14 public int getCount() {
15 return items.size();
16 }
17
18 @Override
19 public Object getItem(int position) {
20 return items.get(position);
21 }
22
23 @Override
24 public long getItemId(int position) {
25 return position;
26 }
27
28 @Override
29 public boolean hasStableIds() {
30 return false;
31 }
32
33 @Override
34 public View getView(int position, View convertView, ViewGroup parent) {
35 ViewHolder vh =null;
36 if(convertView==null){
37 vh = new ViewHolder();
38 convertView = mInflater.inflate(R.layout.item, null);
39 vh.tv = (TextView) convertView.findViewById(R.id.tvShow);
40
41 convertView.setTag(vh);
42 }else{
43 vh = (ViewHolder) convertView.getTag();
44 }
45
46 vh.tv.setText(items.get(position));
47
48 return convertView;
49 }
50
51 @Override
52 public int getItemViewType(int position) {
53 return 1;
54 }
55
56 @Override
57 public int getViewTypeCount() {
58 return 1;
59 }
60
61 @Override
62 public boolean isEmpty() {
63 return false;
64 }
65
66 @Override
67 public boolean areAllItemsEnabled() {
68 return false;
69 }
70
71 @Override
72 public boolean isEnabled(int position) {
73 return true;
74 }
75
76 }

  有了这个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

  

时间: 2024-10-21 03:19:08

Android:ListView之ViewHolder的相关文章

Android——ListView布局+适配器(三)

Android--ListView布局+适配器(三) package com.example.administrator.newstop; import android.os.Bundle; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import andro

Android——ListView多布局+适配器(二)

Android--ListView多布局+适配器(二) <span style="font-size:18px;">package com.example.administrator.newstop.entity; /** * Created by Administrator on 2016/8/4. */ public class News { private String title; private String pubDate; private int img; p

Android ListView复杂列表优化实践

原文:Android ListView复杂列表优化实践 很多社交App都不免会涉及到复杂的列表元素实现,一个列表上面可能大量的图片,不定长的评论列表,给手机端的程序员带来了不少的挑战.本文就是在实现复杂的列表滑动的情况下,利用已知的优化方法指导下的一次优化实践,旨在提升ListView的滑动流畅度,为用户带来良好的体验. 1:设计稿: 这是列表中可能出现的ItemView,有两种,但是又有许多相同的地方,比如一样有点赞的图片,评论等...其中,评论和点赞的数量是可变的. 2:使用一般布局带来的问

[转]Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件

Android ListView最佳处理方式,ListView拖动防重复数据显示,单击响应子控件. 1.为了防止拖动ListView时,在列表末尾重复数据显示.需要加入 HashMap<Integer,View> lmap = new HashMap<Integer,View>();其中Integer为列表位置,View为子项视图,加入数据前首先if (lmap.get(position)==null) ,满足条件时,加入lmap.put(position, convertView

android listview级联三菜单选择地区,本地数据库sqlite级联地区,item选中不变色

前言:因为找了N多网上的资源都没有好的解决方案,别人都是只给思路没给具体源码,真TMD纠结,干嘛求别人,自己动手才是真,最痛恨那些所谓大牛的作风,给了点点代码就让别人去想,你让我们这种小白情何于堪!!!!!!此例是基于listview来实现本地sqlite实现的! 二话不说,程序猿求的是有图有真相有源码!大家下载后有什么问题可以找到本人:QQ508181017 核心代码如下 1.数据库操作类 package com.icq.demo.db; import java.util.ArrayList;

Android——ListView与适配器

Android--ListView与适配器 1.抽屉布局  Drawer <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.

Android ListView条目全选功能,不用checkbox实现!

大家好,翻了翻以前的笔记,发现了一个我特别标记的功能,那就是ListView全选功能,顿时想起了我那个时候苦逼的生涯,由于我大学机械出身,大学毕业了都不知道什么叫代码,在58干了一段销售.实在是干不下去了,不干了就得在网上找工作,就喜欢干电脑相关的工作,有一天,一家培训机构给我打来电话让我去面试,我以为让我去工作那,谁知道是忽悠我去培训,我当然不可能花钱了,就直接回去了,想了几天,除了销售我真不知道干啥,咬咬牙,就花钱培训了.我擦,咋说这到了,不跟你们说了,还是写下面的这个功能吧,虽然很简单,但

Android ListView加载更多

先看效果: ListView的footer布局: <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap

android listview 异步加载图片并防止错位

网上找了一张图, listview 异步加载图片之所以错位的根本原因是重用了 convertView 且有异步操作. 如果不重用 convertView 不会出现错位现象, 重用 convertView 但没有异步操作也不会有问题. 我简单分析一下: 当重用 convertView 时,最初一屏显示 7 条记录, getView 被调用 7 次,创建了 7 个 convertView. 当 Item1 划出屏幕, Item8 进入屏幕时,这时没有为 Item8 创建新的 view 实例, Ite