Android理解RecyclerView的緩存機制

? ? ? Recyclerview通過內(nèi)部類Recycler管理的緩存,緩存的是ViewHolder(內(nèi)部包含子View),這樣在滑動時可以復用子View,在某些情況下,還可以復用子View綁定的數(shù)據(jù)。所以本質(zhì)上緩存是為了減少重復繪制View和綁定數(shù)據(jù)的時間,從而提高了滑動時的性能。

Recycler緩存ViewHolder對象有4個等級,優(yōu)先級從高到底依次為:

1、ArrayList mAttachedScrap --- 緩存屏幕中可見范圍的ViewHolder

2、ArrayList mCachedViews? ----? 緩存滑動時即將與RecyclerView分離的ViewHolder,按子View的position或id緩存,默認最多存放2個

3、ViewCacheExtension mViewCacheExtension? ?---? 開發(fā)者自行實現(xiàn)的緩存

4、RecycledViewPool mRecyclerPool? ? ---? ? ?ViewHolder緩存池,本質(zhì)上是一個SparseArray,其中key是ViewType(int類型),value存放的是 ArrayList< ViewHolder>,默認每個ArrayList中最多存放5個ViewHolder。

? ? ? 通過mAttachedScrap、mCachedViews及mViewCacheExtension獲取的ViewHolder不需要重新創(chuàng)建布局及綁定數(shù)據(jù);通過緩存池mRecyclerPool獲取的ViewHolder不需要重新創(chuàng)建布局,但是需要重新綁定數(shù)據(jù);如果上述緩存中都沒有獲取到目標ViewHolder,那么就會回調(diào)Adapter#onCreateViewHolder創(chuàng)建布局,以及回調(diào)Adapter#onBindViewHolder來綁定數(shù)據(jù)。

接下來重點理解下mViewCacheExtension 的使用

我們已經(jīng)知道ViewCacheExtension屬于第三級緩存,需要開發(fā)者自行實現(xiàn),那么ViewCacheExtension在什么場景下使用?又是如何實現(xiàn)的呢?

? ? ? 那就是Recycler本身已經(jīng)設置了好幾級緩存了,為什么還要留個接口讓開發(fā)者去自行實現(xiàn)緩存呢?關(guān)于這一點,談一談我的理解:來看看Recycler中的其他緩存,其中mAttachedScrap用來處理可見屏幕的緩存;mCachedViews里存儲的數(shù)據(jù)雖然是根據(jù)position來緩存,但是里面的數(shù)據(jù)隨時可能會被替換的;再來看mRecyclerPool,mRecyclerPool里按viewType去存儲ArrayList< ViewHolder>,所以mRecyclerPool并不能按position去存儲ViewHolder,而且從mRecyclerPool取出的View每次都要去走Adapter#onBindViewHolder去重新綁定數(shù)據(jù)。假如我現(xiàn)在需要在一個特定的位置(比如position=0位置)一直展示某個View,且里面的內(nèi)容是不變的,那么最好的情況就是在特定位置時,既不需要每次重新創(chuàng)建View,也不需要每次都去重新綁定數(shù)據(jù),上面的幾種緩存顯然都是不適用的,這種情況該怎么辦呢?可以通過自定義緩存ViewCacheExtension實現(xiàn)上述需求。

ViewCacheExtension適用場景:ViewHolder位置固定、內(nèi)容固定、數(shù)量有限時使用

實現(xiàn)自定義緩存ViewCacheExtension

? ? class MyViewCacheExtension extends RecyclerView.ViewCacheExtension {

? ? ? ? @Nullable

? ? ? ? @Override

? ? ? ? public View getViewForPositionAndType(@NonNull RecyclerView.Recycler recycler, int position, int viewType) {

? ? ? ? ? ? //如果viewType為TYPE_SPECIAL,使用自己緩存的View去構(gòu)建ViewHolder

? ? ? ? ? ? // 否則返回null,會使用系統(tǒng)RecyclerPool緩存或者從新通過onCreateViewHolder構(gòu)建View及ViewHolder

? ? ? ? ? ? return viewType == DemoAdapter.TYPE_SPECIAL ? adapter.caches.get(position) : null;

? ? ? ? }

? ? }



?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容