RecyclerView 緩存原理

RecyclerView 緩存原理

通常認爲RecyclerView有四級緩存,RecyclerView的緩存是通過Recycler類來完成的,方法的入口:

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

緩存的內容是ViewHolder,緩存的地方,是Recycler的幾個list:

final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<ViewHolder>();
private ArrayList<ViewHolder> mChangedScrap = null;

final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();

private final List<ViewHolder>
        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<ViewHolder> mScrapHeap = new ArrayList<>();
	int mMaxScrap = DEFAULT_MAX_SCRAP;
	long mCreateRunningAverageNs = 0;
	long mBindRunningAverageNs = 0;
}
SparseArray<ScrapData> 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的緩存數量,改成你需要的量

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章