一、緩存機制
分析RecyclerView
緩存機制源碼的一系列文章,分析的很清楚:
1. 總結
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()
動態設置。
ViewCacheExtension
開發者可自定義的一層緩存,是虛擬類ViewCacheExtension
的一個實例,開發者可實現方法getViewForPositionAndType(Recycler recycler, int position, int type)
來實現自己的緩存。
RecycledViewPool
RecycledViewPool
類是用來緩存ViewHolder
用,如果多個RecyclerView
之間用setRecycledViewPool(RecycledViewPool)
設置同一個RecycledViewPool
,他們就可以共享ViewHolder
。
1.1 四級緩存
//1.一級緩存:mAttachedScrap 一級緩存中用來存儲屏幕中顯示的ViewHolde
final ArrayList<ViewHolder> mAttachedScrap = new ArrayList<>();
//2.二級緩存:mCacheViews 用來存儲屏幕外的緩存
final ArrayList<ViewHolder> mCachedViews = new ArrayList<ViewHolder>();
//3.三級緩存:mViewCacheExtension 根據coder自己定義的緩存規則
private ViewCacheExtension mViewCacheExtension;
//4.四級緩存:mRecyclerPool 當屏幕外緩存的大小大於2,便放入mRecyclerPool中緩存。
RecycledViewPool mRecyclerPool;
Recycler有4個層次用於緩存ViewHolder對象,優先級從高到底依次爲ArrayList mAttachedScrap、ArrayList mCachedViews、ViewCacheExtension mViewCacheExtension、RecycledViewPool mRecyclerPool。如果四層緩存都未命中,則重新創建並綁定ViewHolder對象
1.2 緩存性能
緩存 | 重新創建ViewHolder |
重新綁定數據 |
---|---|---|
mAttachedScrap | false | false |
mCachedViews | false | false |
mRecyclerPool | false | true |
1.3 緩存容量
-
mAttachedScrap
:沒有大小限制,但最多包含屏幕可見表項。 -
mCachedViews
:默認大小限制爲2,放不下時,按照先進先出原則將最先進入的ViewHolder
存入回收池以騰出空間。 -
mRecyclerPool
:對ViewHolder
按viewType
分類存儲(通過SparseArray
),同類ViewHolder
存儲在默認大小爲5的ArrayList
中。
1.4 緩存用途
-
mAttachedScrap
:用於佈局過程中屏幕可見表項的回收和複用。 -
mCachedViews
:用於移出屏幕表項的回收和複用,且只能用於指定位置的表項,有點像“回收池預備隊列”,即總是先回收到mCachedViews
,當它放不下的時候,按照先進先出原則將最先進入的ViewHolder
存入回收池。 -
mRecyclerPool
:用於移出屏幕表項的回收和複用,且只能用於指定viewType
的表項
1.5 緩存結構
-
mAttachedScrap
:ArrayList
-
mCachedViews
:ArrayList
-
mRecyclerPool
:對ViewHolder
按viewType
分類存儲在SparseArray
中,同類ViewHolder
存儲在ScrapData
中的ArrayList
中
1.6 緩存存入步驟
-
第一級緩存執行流程
RecyclerView.scrollBy()–>RecyclerView.scrollByInternal()–>RecyclerView.resumeRequestLayout()–>RecyclerView.dispatchLayout()–>RecyclerView.dispatchLayoutStep1()–>LayoutManager.onLayoutChildren()–>LayoutManager.scrapOrRecycleView()–>Recycler.scrapView() -
第二級緩存執行流程 執行條件 第一級緩存不要的纔給第二級緩存
Recycler.recycleViewHolderInternal() -
第四級緩存 第二級緩存滿了 纔給第四級緩存
1.7 緩存獲取步驟
LinearLayoutManager.onLayoutChildren()–>LinearLayoutManager.fill()–>LinearLayoutManager.layoutChunk()–>LayoutState.next()–>Recycler.getViewForPosition()–>Recycler.getViewForPosition()–>Recycler.tryGetViewHolderForPositionByDeadline()