文章目录
Android开发学习笔记之RecycleView缓存机制
概述
RecycleView作为Android开发中最为常见的一个View,其布局灵活,功能强大,在日常的开发中,已经基本取代了List View和GridView成为了我们在使用列表的不二之选。但是,尽管使用频率相当高,在开发中使用RecycleView还是经常会碰到各种问题,而其中最常见的就是由于RecycleView的缓存复用机制而带来的各种显示问题了。因此,为了尽量避免这类问题,我们需要了解其复用机制,以及其实现原理。
为什么需要缓存机制呢?
首先,提出一个问题,就是为什么RecycleView需要缓存复用机制呢?我们知道RecycleView通常作为一个列表在应用中使用,往往可能会存在的大量的数据需要滑动来显示item,那么在滑动的过程中,就不可避免地需要去移除和添加子View,如果每次使用子View都要去重新创建,肯定会影响滑动的流畅性,所有RecycleView需要使用缓存来复用子View,减少绘制。所以本质上缓存是为了减少重复绘制View和绑定数据的时间,从而提高了滑动时的性能。
RecycleView的缓存机制
在RecycleView的实现中,其缓存复用机制是一大核心,这其实从其名字中的Recycle
就可以知道。RecycleView复用机制的核心是通过内部类Recycle
实现的,其基本单位是ViewHolder
,其内部包含有子View的引用,通过缓存ViewHolder
来实现View的复用,某些情况下还能复用子View绑定的数据。
基本原理
在RecycleView的缓存机制中包含有四层缓存:
- mAttachedScrap、mChangedScrap:一级缓存;mAttachedScrap用于缓存当前屏幕可见范围存在的ViewHolder,可用于数据集发生变化重新layout过程,其数据是干净的,可以直接复用,无需重新绑定数据。mChangedScrap用于缓存发生变化的ViewHolder,属于脏数据,需要重新绑定数据。
- mCachedViews:二级缓存;用于缓存滑出屏幕外的ViewHolder,也是干净的可以直接复用,默认大小为2,超出缓存大小后会根据FIFO先入先出的规则将先添加进缓存的ViewHolder放入mRecyclerPool中。
- mViewCacheExtension:三级缓存;预留给开发者自行扩展的缓存,一般不做使用。
- mRecyclerPool:四级缓存;用于缓存滑出屏幕外的ViewHolder,当超出mCachedViews的缓存大小时,会被缓存到mRecyclerPool,默认大小为5,其缓存的数据存入先都被重置,需要重新绑定数据,根据ItemViewType缓存数据。
我们在之前上述介绍过,Recycle
类就是RecycleView缓存机制的核心类,上述四层缓存都是由该类实现的,我们可以看下该类的基本变量声明,如下:
public final class Recycler {
//一级缓存,layout时使用
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
ArrayList<ViewHolder> mChangedScrap = null;
//二级缓存,当view滑出屏幕时会被缓存到该list中
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
private final List<ViewHolder>
mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);
//默认缓存大小,2
private int mRequestedCacheMax = DEFAULT_CACHE_SIZE;
int mViewCacheMax = DEFAULT_CACHE_SIZE;
//四级缓存,超出mCachedViews最大缓存数量后,会被添加到该缓存池中
RecycledViewPool mRecyclerPool;
//三级缓存,开发者扩展
private ViewCacheExtension mViewCacheExtension;
static final int DEFAULT_CACHE_SIZE = 2;
...
}
我们可以看到,在Recycle
类中,声明了上述的四级缓存,其中mViewCacheExtension是留给我们开发时自己进行扩展的,基本不会使用,我们暂时忽略。我们可以看到除了mRecyclerPool
其余的缓存都是一个ViewHolder的ArrayList,这说明了,RecycleView缓存的基本单位就是ViewHolder。其实mRecyclerPool
也是如此,如下:
public static class RecycledViewPool {
//默认缓存大小
private static final int DEFAULT_MAX_SCRAP = 5;
static class ScrapData {
//缓存
final ArrayList