Android性能优化之Listview(ViewHolder重用机制)

Android性能优化之Listview(ViewHolder重用机制),相信大家在很多时候都会用到ListView这个控件,因为确实是用的很多很多,但是有木有遇到过当数据很多很多的时候,往下滑ListView时有时候会卡顿,这就需要我们来优化它了。

ListView优化主要有下面几个方面:

1、convertView重用

2、ViewHolder的子View复用

3、缓存数据复用

一、convertView重用

首先讲下ListView的原理:ListView中的每个item显示都需要Adapter调用一次getView(),这个方法会传入一个convertView参数,返回的view即item的view。如果item数量足够大,再为每个item创建view对象,必将占用大量的内存。即创建View对象(mInflater.inflate(R.layout.lv_item, null);从xml中生成View,这是属于IO操作)是耗时操作,所以必将影响性能。Android提供了一个叫做Recycler(反复循环)的构件,就是当ListView的Item从滚出屏幕视角之外,对应Item的View会被缓存到Recycler中,相应的会重生成一个item。而此时调用的getView中的参数convertView就是被缓存的view,所以说如果能重用这个convertView,就会大大改善性能。
Android性能优化之Listview(ViewHolder重用机制)
1.如果你有10亿个项目(item),其中只有可见的项目存在内存中,其他的在Recycler中

2.ListView先请求一个type1视图(getView),然后请求其他可见的项目。conVertView在getView中时null的

3.当item1滚出屏幕,并且一个新的项目从屏幕地段上来时,ListView再请求一个type1视图。convertView此时不是空值了,它的值是item1.你只需要设定新的数据返回convertView,不必重新创建一个视图。这样直接使用convertView从而减少了很不不必要view的创建

!!!!!!更快的方式是定义一个ViewHolder,将convertView的tag设置为ViewHolder,不为空是重新使用

ViewHolder只是将需要缓存的那些view封装好,convertView的setTag才是将这些缓存起来供下次调用

当你的listview里布局多样化的时候 viewholder的作用就有比较明显的体现了。 当然了,单一模式的布局一样有性能优化的作用 只是不直观。假如你2种模式的布局 当发生回收的时候 你会用setTag分别记录是哪两种 这两种模式会被封装到viewholder中进行保存方便你下次使用。 VH就是个静态类 与缓存无关的

我们怎么重用convertView呢?
Android性能优化之Listview(ViewHolder重用机制)
如图,当这个convertView不存在时,即第一次使用它,我们就创建一个item布局的View对象并赋给convertView,以后使用convertView时,只需从convertView中getTag取出来就可以,不需要再次创建item的布局对象了,这样便提高了性能。

二、使用ViewHolder重用

我们都知道在getView()方法中的操作是这样的:先从xml中创建view对象(inflate操作,我们采用了重用convertView方法优化),然后在这个view去findViewById,找到每一个item的子View的控件对象,如:ImageView、TextView等。这里的findViewById操作是一个树查找过程,也是一个耗时的操作,所以这里也需要优化,就是使用ViewHolder,把每一个item的子View控件对象都放在Holder中,当第一次创建convertView对象时,便把这些item的子View控件对象findViewById实例化出来并保存到ViewHolder对象中。然后用convertView的setTag将viewHolder对象设置到Tag中, 当以后加载ListView的item时便可以直接从Tag中取出复用ViewHolder对象中的,不需要再findViewById找item的子控件对象了。这样便大大提高了性能。