一、缓存机制
由于ListView也是由它的缓存机制,并且比RecyclerView简单很多。而且RecyclerView缓存的本质和ListView的是差不多的,所以我先从简单的ListView看起。
二、ListView的缓存机制
每当要找一个目标 convertView时,ListView先会去找 RecycleBin(回收站)
第一步:RecycleBin在ActiveView(即在屏幕上显示的、活跃的View)中寻找有没有目标View
第二步:如果第一步没有找到,则取 Scrap View(即废弃的,丢掉的View)中寻找有没有目标View
第三步:如果前两步都没有缓存的目标View,则通过 getView()里面去创建一个新的View。
再看下图:
-
假如框框是我们的屏幕,那么框框里面显示的View就是ActivieView。
-
这个时候,假设屏幕往上滑动,那么最下面的View是没有创建过的,这个时候RecycleBin就会去ScrapView中找,假如我们新的convertView的type是1,而 ScrapView中正好也有type为1的View,那么,ListView就会通过getView()返回这个View。
-
由于这个View的数据是脏的,所以需要对它重新的赋值。
为什么会有ActiveView缓存呢?这些View都没有离开屏幕,我们为什么要缓存它?
在Android的屏幕渲染机制中,我们知道是每隔16.666ms刷新一次View,在刷新的时候,需要清干净屏幕上的内容,然后再显示,或者我们切到别的界面,再切回来,这个时候屏幕要渲染数据,如果ListView这个时候发现Adapter数据没有变,那么就会直接从ActiveViews中渲染数据。
这就是ListView的缓存机制的原理。它是二级实现。它的本质就是复用。
三、RecyclerView的缓存机制
RecyclerView实现的缓存层级比ListView更多,它有四级缓存如下:
- Scrap
和ListView中的ActiveView一样。
查看当前屏幕上是否有View可以复用。
-
Cache
-
ViewCacheExtension
开发者自己实现的缓存策略
- RecycledViewPool
列表池,和复用也有关系。
当四级缓存都找不到目标View时,并通过我们 onCreateViewHolder()来创建。
1.缓存场景
- ScapView
和ListView中的ActiveView作用一致,具体看3.1节。
- Cache
只存储少量的,刚从屏幕上消失的item。只关系position
它的作用是在用户来回滑时,直接通过position在Cache中拿到对应的View。直接渲染在屏幕上。
- ViewCacheExtension
开发中自定义缓存机制。平时开发中基本也没用到,等下看个例子。
- RecycledViewPool
复用池,它可以存储大量的,消失很久的item。如果上述1、2、3都不能取出时,则从RecycledViewPool池中取出。这个时候由于数据是脏的,所以需要重新渲染。
上述1、2级缓存是直接取出来用。不会走 onCreateViewHolder 和 onBindViewHolder
第4级不用走 create方法,但是要走 onBindViewHolder()进行数据渲染。
三、ViewHoler作用
不实现ViewHolder的getView无论如何,每次都要通过findViewById去寻找目标控件,而使用了ViewHolder之后,它不用每次都做findViewById()去寻找目标控件,这也正是ViewHolder解决的问题,这也解答了为什么使用了ViewHolder能提高性能?
findViewById在Android底层,所有资源ID应该是以树的形式存储的,然后这个方法实现是通过 DFS去寻找目标控件的,DFS的时间复杂度是 O(n)。
O(n)的复杂度对于程序开发来说,其实是算快的,但是在convertView非常多,view里面的控件也非常多,那每次getView都时候都要调用findViewById,这对性能来说还是会容易产生大量的消耗。
所以ViewHolder的出现,就是为了减少findViewById()的使用。