RecyclerView 缓存原理

RecyclerView 缓存原理

通常认为RecyclerView有四级缓存,RecyclerView的缓存是通过Recycler类来完成的,方法的入口:

public View getViewForPosition(int position) {
    return getViewForPosition(position, false);
}

缓存的内容是ViewHolder,缓存的地方,是Recycler的几个list:

final ArrayList mAttachedScrap = new ArrayList();
private ArrayList mChangedScrap = null;

final ArrayList mCachedViews = new ArrayList();

private final List
        mUnmodifiableAttachedScrap = Collections.unmodifiableList(mAttachedScrap);

private int mViewCacheMax = DEFAULT_CACHE_SIZE;

private RecycledViewPool mRecyclerPool;

private ViewCacheExtension mViewCacheExtension;

private static final int DEFAULT_CACHE_SIZE = 2;
第一级缓存

mAttachedScrap: 用于缓存显示在屏幕上的 item 的 ViewHolder
mChangedScrap: 还是屏幕内的ViewHolder,没看懂啥意思,可能是用于缓存局部改变时候的holder

第二级缓存

mCachedViews:划出屏幕外的item,这个list的默认大小是2,

第三级缓存

mViewCacheExtension:自定义缓存,RecyclerView默认是没有实现的,留给开发者自己实现

第四级缓存

mRecyclerPool:mCachedViews的数量达到上限之后,会把ViewHolder存入mRecyclerPool。mRecyclerPool用SparseArray来缓存进入这一级的ViewHolder:

static class ScrapData {
    final ArrayList mScrapHeap = new ArrayList<>();
    int mMaxScrap = DEFAULT_MAX_SCRAP;
    long mCreateRunningAverageNs = 0;
    long mBindRunningAverageNs = 0;
}
SparseArray mScrap = new SparseArray<>();

但存在mRecyclerPool的 ViewHolder 的数据信息会被重置掉,相当于 ViewHolder 是一个重创新建的一样,所以需要重新调用 onBindViewHolder 来绑定数据,所以尽量不要让ViewHolder进入这一层

缓存优化

进入RecyclerPool的ViewHolder会被重置,会从新执行bindViewHolder,所以从效率上来讲,很费性能。

所以为了避免进入这一层缓存,可以在在第三层自定义缓存自己实现,也就是自定义mViewCacheExtension。在这里自己维护一个viewType对应View的SparseArray。这样可以避免因为多种type导致的holder重建。

public abstract static class ViewCacheExtension {
    @Nullable
    public abstract View getViewForPositionAndType(@NonNull Recycler recycler, int position,
                int type);
    }

注意getViewForPositionAndType返回的是view而不是ViewHolder,然后会通过view的layoutParams拿到ViewHolder。

第二可以增大mCachedViews的缓存数量,改成你需要的量

你可能感兴趣的:(RecyclerView 缓存原理)