值得收藏的ViewHolder工具类实现

移动开发 Android
作为最伟大的第二十二世纪的程序员们,脱掉、搞上永远是我们最真挚的追求,所以我们要怎么将ViewHolder从BaseAdapter中脱掉呢?绝非不是不用,而是要将其搞成一个华丽丽的工具类实现,收入角落那个寂寞得tools类中。

前言

在开发APP的过程中,攻城狮少不了要跟ListView、GridView这些组件眉来眼去,暗送几波秋波。自然原生态美人BaseAdapter更是程序员的最爱,有了它,我们想怎么干就能怎么干,嘿嘿,你懂的O(∩_∩)O哈哈~

但是,每次写一个BaseAdapter,我们都很自觉的给他写一个ViewHolder,一两个还好,万一应用程序中有数不清的ListView,呵呵~你妹!千篇一律,看得都审美疲劳。作为最伟大的第二十二世纪的程序员们,脱掉、搞上永远是我们最真挚的追求,所以我们要怎么将ViewHolder从BaseAdapter中脱掉呢?绝非不是不用,而是要将其搞成一个华丽丽的工具类实现,收入角落那个寂寞得tools类中。

[[180596]]

ViewHolder的实现

我觉得应该简略的介绍下ViewHolder的实现,谷歌很聪明的在Adapter中运用了复用View的思想,自然让我们的屌丝机也能泡上一些白富美应用多了一点点可能。ViewHolder的具体实现基本体现在BaseAdapter的 getView(int position, View convertView, ViewGroup parent) 这个方法里面,参见下面的代码: 

  1. @Override 
  2.  
  3. public View getView(int position, View convertView, ViewGroup parent) { 
  4.  
  5.     ViewHolder holder; 
  6.  
  7.     if (convertView == null) { 
  8.  
  9.         convertView = inflater.inflate(R.layout.listview_item_layout, parent, false); 
  10.  
  11.         holder = new ViewHolder(); 
  12.  
  13.         holder.studentName = (TextView) convertView.findViewById(R.id.student_name); 
  14.  
  15.         holder.studentAge = (TextView) convertView.findViewById(R.id.student_age); 
  16.  
  17.         convertView.setTag(holder); 
  18.  
  19.     } 
  20.  
  21.     else { 
  22.  
  23.         holder = (ViewHolder) convertView.getTag(); 
  24.  
  25.     } 
  26.  
  27.     Student data = (Student) getItem(position); 
  28.  
  29.     holder.studentName.setText(data.getName()); 
  30.  
  31.     holder.studentAge.setText(data.getAge()); 
  32.  
  33.     return convertView; 
  34.  
  35.  
  36.   
  37.  
  38. class ViewHolder { 
  39.  
  40.     public TextView studentName; 
  41.  
  42.     public TextView studentAge; 
  43.  
  44.  

很明显,大家不要问我ViewHolder在哪里,稍微把目光往上扶一扶就看到那个大大的 class ViewHolder 。这里的ViewHolder用法主要有两个地方,一是 convertView 的复用,二是 ViewHolder 也就是 convertView 里面的索引的复用。具体的用法不熟悉的话可以百度一下,再往下说就对不起我今天这篇博文了,因为在这里写这个代码的目的,肯定不是介绍你怎么用ViewHolder,只是想告诉你:传统的ViewHolder的写法,是多么的臃肿!而且对于每一个新的BaseAdapter,你都得无聊的实现一次又一次,OH~

ViewHolder的工具类实现

自然,脱光要从小,行动要趁早。既然我们烦了,就把它写成一个工具类咯。参见下面的代码

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

这是工具类的实现,稍微说下实现的原理:

1、ViewHolder既然是依赖View的Tag存放,但是以一个 SparseArray 集合存放。

2、判断View里的Tag是否存在viewHolder,不存在,赶紧叫她生一个。

3、然后在viewholder(也就是SparseArray)寻找View的索引,如果没有,赶紧findViewById一个put进去顺便return出来,如果已经存在,皆大欢喜,直接用呗。

贴个BaseAdapter里面使用的代码: 

  1. @Override 
  2.  
  3. public View getView(int position, View convertView, ViewGroup parent) { 
  4.  
  5.     if (convertView == null) { 
  6.  
  7.         convertView = inflater.inflate(R.layout.listview_item_layout, parent, false); 
  8.  
  9.     } 
  10.  
  11.     TextView name = Tools.ViewHolder.get(convertView, R.id.student_name); 
  12.  
  13.     TextView age = Tools.ViewHolder.get(convertView, R.id.student_age); 
  14.  
  15.      
  16.  
  17.     Student data = (Student) getItem(position); 
  18.  
  19.     name.setText(data.getName()); 
  20.  
  21.     age.setText(data.getAge()); 
  22.  
  23.      
  24.  
  25.     return convertView; 
  26.   

简洁明了,不用多说~~~嘿嘿,后面如果要写ViewHolder,直接Tools工具类调用,省心不废脑。。

分析可行性

既然要作为工具类使用,我们有必要先评估这个工具值不值得我们使用。

一般来说,我们可以从以下几个方面进行评估:易用性? 内存泄露? 性能提升? 健壮性?等等等。。。。。。

易用性:工具类的最大特性就是易用简约,这个ViewHolder的写法就是典型的拿来就用的主义,根本不用我们操心写些适配的代码,直接传入View和id,高内聚松耦合。并且采用了<T extends View> T的泛型模板的方法,自动与外部的View子类适配,不用我们手动去强制装换。

内存泄露:有些初学者,看到static方法就回固执的认为 SparseArray<View> viewHolder 这个变量会存在内存泄露,但是java告诉我们,这个变量的小命仅仅在方法执行之中,方法完毕,GC回收;存在ViewHolder一如既往放在View的Tag中,一旦View被回收,ViewHolder自然消失。不信,打开DDMS,用你28青年的手速不停刷listView试试,保证对象基本稳定在一个值。

性能提升:在这里我们发现用了 SparseArray 这个集合而不是 HashMap ,我们知道 SparseArray 是Android的一个工具类,是官方推荐用来代替 HashMap<Integer,E> 的一个类,它的内部采用了二分查找的实现提高了查找效率,而且不是一点两点的哦,谁用谁知道;具体内容想要了解,可以度娘谷哥或者左转源码。

所以,作为一个工具类,它是完全合格的,赶紧把它拷贝到你的tools、util里面,然后我们就可以开心加愉悦的优雅用起ViewHolder了。。 

责任编辑:庞桂玉 来源: 安卓开发精选
相关推荐

2015-05-06 10:06:48

AndroidViewHolder

2015-12-02 11:05:48

2020-11-27 15:00:22

Kubernetes程序工具

2020-10-10 11:14:15

工具软件Linux

2020-06-24 16:20:02

LinuxCPU监控工具

2020-05-28 15:14:05

LinuxCPU监控工具

2020-01-29 19:34:57

工具黑客语音合成

2023-07-26 00:40:25

AI工具备忘录

2017-03-23 10:21:57

CSS3动效库前端

2019-04-03 05:09:59

网络扫描无线网络监控

2019-04-22 15:00:05

CSS前端开发

2019-04-01 05:02:48

搜索架构检索

2022-01-05 07:07:36

网络

2020-12-25 17:19:27

工具网络网站

2019-10-12 00:03:07

MyCat数据库分库分表

2013-07-22 10:01:03

JavascriptWeb

2019-02-26 15:17:15

工具性能数据

2015-06-09 14:23:43

CSS收藏CSS框架

2022-06-28 10:20:58

微服务架构RPC

2019-08-15 14:33:26

点赞
收藏

51CTO技术栈公众号