很多人提起RecycleView和ListView的时候必定会提起两者的差异,都说RecycleView好,多布局,多缓存,等等。今天我们结合下源码理清一下RecycleView的多级缓存机制,我研究代码喜欢先从宏观了解下整体,然后再分个进入。所以等会先介绍下管理RecycleView的缓存类,然后会从某个类开始切入,分析。
Recyclerview的缓存类
RecycleView的四级缓存是由三个类共同作用完成的,Recycler、RecycledViewPool和ViewCacheExtension。
Recycler
用于管理已经废弃或者与RecyclerView分离的ViewHolder,这里面有两个重要的成员
- 屏幕内缓存 屏幕内缓存指在屏幕中显示的ViewHolder,这些ViewHolder会缓存在mAttachedScrap、mChangedScrap中
mChangedScrap 表示数据已经改变的viewHolder列表 mAttachedScrap未与RecyclerView分离的ViewHolder列表 - 屏幕外缓存 当列表滑动出了屏幕时,ViewHolder会被缓存在 mCachedViews ,其大小由mViewCacheMax决定,默认DEFAULT_CACHE_SIZE为2,可通过Recyclerview.setItemViewCacheSize()动态设置。
RecycledViewPool
RecycledViewPool类是用来缓存ViewHolder用,如果多个RecyclerView之间用setRecycledViewPool(RecycledViewPool)设置同一个RecycledViewPool,他们就可以共享ViewHolder。
ViewCacheExtension
开发者可自定义的一层缓存,是虚拟类ViewCacheExtension的一个实例,开发者可实现方法getViewForPositionAndType(Recycler recycler, int position, int type)来实现自己的缓存。
Recyclerview结合源码分析缓存
看过了上面的介绍你应该有了一个总体的印象,现在带着这些印象我们去源码里面看看到底怎么实现的,我会从第一个Recycler开始,然后理清楚,各个缓存中是如何变化的,如何从一级变到另外一级,其代码具体是怎样的逻辑!首先我们先点进Recycler,映入眼帘的就是这些成员(只截取部分):
public final class Recycler {
//一级缓存中用来存储屏幕中显示的ViewHolde
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<ViewHolder>();
private ArrayList<ViewHolder> mChangedScrap = null;
//二级缓存中用来存储屏幕外的缓存
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
//暂可忽略 mAttachedScrap的不可变视图
private final List<ViewHolder>
mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);
//当前屏幕外缓存大小,数量为2,即本代码片最后一个DEFAULT_CACHE_SIZE 成员的值,可变。
private int mViewCacheMax = DEFAULT_CACHE_SIZE;
//四级缓存当屏幕外缓存的大小大于2,便放入mRecyclerPool中缓存。
private RecycledViewPool mRecyclerPool;
//三级缓存自定义缓存,根据coder自己定义的缓存规则。
private ViewCacheExtension mViewCacheExte