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的緩存數量,改成你需要的量