Android数据适配器(Adapter)优化:高效ViewHolder

移动开发 Android
在使用Listview或GridView的时候,往往需要自定义数据适配器,一般都要覆写getView(),在该方法中有一个convertView参数,该参数就是用来加载数据时的View。

在使用Listview或GridView的时候,往往需要自定义数据适配器,一般都要覆写getView(),在该方法中有一个convertView参数,该参数就是用来加载数据时的View。

初学者简单但低效的方式

  1. public View getView(int position, View convertView, ViewGroup parent) { 
  2.   
  3.   View item= inflater.inflate(R.layout.good_list_item, nullfalse); 
  4.         
  5.   ImageView img = (ImageView) item.findViewById(R.id.img); 
  6.   TextView price = (TextView) item.findViewById(R.id.price); 
  7.   img.setImageResource(R.drawable.ic_launcher); 
  8.   price.setText("$"+list.get(position).price); 
  9.            
  10.   return item; 
  11.  } 

每次加载view,都要重新建立很多view对象,如果某条listview中有一万条数据,这种加载方式就歇菜了。

利用convertView

利用Android的Recycler机制,利用convertView来重新回收View,效率有了本质提高。View的每次创建是比较耗时的,因此对于getview方法传入的convertView应充分利用 != null的判断 。

  1. public View getView(int position, View convertView, ViewGroup parent) { 
  2.  
  3.       if(convertView==null){ 
  4.           convertView = inflater.inflate(R.layout.good_list_item, nullfalse); 
  5.       } 
  6.       TextView tv_price = (TextView)convertView.findViewById(R.id.price) 
  7.       ImageView iv = (ImageView)convertView.findViewByID(R.id.img); 
  8.        
  9.       return convertView; 
  10.   } 

使用ViewHolder

ViewHolder将需要缓存的view封装好,convertView的setTag才是将这些缓存起来供下次调用。 当你的listview里布局多样化的时候 viewholder的作用体现明显,效率再一次提高。 View的findViewById()方法也是比较耗时的,因此需要考虑只调用一次,之后就用View.getTag()方法来获得ViewHolder对象。

  1. class ViewHolder{ 
  2.       ImageView img; 
  3.       TextView price; 
  4.  } 
  5. public View getView(int position, View convertView, ViewGroup parent) { 
  6.       ViewHolder holder = new ViewHolder(); 
  7.       if(convertView==null){ 
  8.          convertView = inflater.inflate(R.layout.good_list_item, nullfalse); 
  9.          holder.img = (ImageView) convertView.findViewById(R.id.img); 
  10.           holder.price = (TextView) convertView.findViewById(R.id.price); 
  11.           convertView.setTag(holder);   
  12.       }else
  13.           holder = (ViewHolder) convertView.getTag(); 
  14.       } 
  15.       //设置holder 
  16.       holder.img.setImageResource(R.drawable.ic_launcher); 
  17.      holder.price.setText("$"+list.get(position).price); 
  18.            
  19.       return convertView; 
  20.   } 

优雅的使用ViewHolder

使用ViewHolder时,每次一遍一遍的findViewById,一遍一遍在ViewHolder里面添加View的定义,view一多,是不是感觉烦爆了,base-adapter-helper这个类库似乎***的解决了这个问题。

其设计思想是使用 SparseArray来存储view的引用,代替了原本的ViewHolder,不用声明一大堆View,简洁明了。

我也自己动手写了一个简单版的ViewHolder。

  1. public class ViewHolder{ 
  2.    
  3.      private final SparseArray<View> views; 
  4.      private View convertView; 
  5.   
  6.       private ViewHolder(View convertView){ 
  7.          this.views = new SparseArray<View>(); 
  8.          this.convertView = convertView; 
  9.          convertView.setTag(this); 
  10.      } 
  11.   
  12.      public static ViewHolder get(View convertView){ 
  13.          if (convertView == null) { 
  14.              return new ViewHolder(convertView); 
  15.          } 
  16.          ViewHolder existedHolder = (ViewHolder) convertView.getTag(); 
  17.          return existedHolder; 
  18.     } 
  19.   
  20.      public <T extends View> T getView(int viewId) { 
  21.          View view = views.get(viewId); 
  22.          if (view == null) { 
  23.              view = convertView.findViewById(viewId); 
  24.              views.put(viewId, view); 
  25.          } 
  26.          return (T) view; 
  27.      } 
  28.  } 

使用的话就超级简单和简洁了:

  1. public View getView(int position, View convertView, ViewGroup parent) { 
  2.          if (convertView == null) { 
  3.              convertView = LayoutInflater.from(context) 
  4.                      .inflate(R.layout.good_list_item, nullfalse); 
  5.          } 
  6.    
  7.          ViewHolder mViewHolder = ViewHolder.get(convertView); 
  8.         TextView price = mViewHolder.getView(R.id.price); 
  9.         //...其他getView 
  10.    
  11.          return convertView; 
  12.      } 

 

责任编辑:闫佳明 来源: stackvoid
相关推荐

2012-08-02 10:46:34

JavaAdapter模式

2013-11-26 16:39:21

Android设计模式

2022-02-18 17:21:29

适配器模式客户端

2020-10-25 08:56:21

适配器模式

2012-09-19 15:29:26

Worklight适配器

2009-12-21 10:26:09

Oracle适配器

2018-10-11 10:38:31

前端JavaScript编程语言

2012-05-16 17:22:11

Java设计模式

2009-11-18 18:08:20

PHP适配器模式

2015-08-07 10:05:37

recyclervie超省写法

2021-02-18 08:39:28

设计模式场景

2013-03-27 09:17:17

Android开发AndroidList

2011-04-28 09:54:50

jQuery

2013-02-26 10:55:47

C#适配器设计模式

2022-02-13 23:33:24

设计模式Java

2021-02-16 08:16:09

适配器模式MybatisJava

2021-08-06 06:51:16

适配器配置Spring

2021-08-16 17:15:19

设计模式Android适配器模式

2009-11-11 17:12:25

ADO.NET批处理

2013-12-10 09:44:00

网络适配器卸载
点赞
收藏

51CTO技术栈公众号