RecyclerView中View的添加複用

本文以通俗的語言,記錄在閱讀RecyclerView源碼時的一些心得🤔。

添加view的過程

  1. 在使用recyclerView的setAdapter方法設置adapter時,會調用RecyclerView的requestLayout()方法,進而執行measure、layout等生命方法;
  2. 何時添加的子view(adapter裏面的一堆):在RecyclerView執行layout時,實際會調用LayoutManager的onLayoutChildren()方法去layout子view,如LinearLayoutManager,方法堆棧:onLayoutChildren()->fill()->layoutChunk()。
  3. 滾動時如何判斷需要add一個子view:核心方法:updateLayoutState(),以向右滑動爲例:①拿到當前最左邊的view(getChildClosestToStart()),一般就是child0;②然後計算還可以向左滑動多遠的距離才需要add一個view,getDecoratedStart()方法:計算最左邊的子view在RecyclerView中的位置(getLeft()+margin)。經過計算之後可以知道:是否需要添加新的子view來填充RecyclerView。

View的複用

下面描述RecyclerView是如何對view進行復用的。
一、RecyclerView的緩存

  1. 一級緩存:mAttachedScrap
    mAttachedScrap中的view不需要重新bindView。ScrapView主要用於對於屏幕內的ChildView的緩存,緩存中的ViewHolder不需要重新Bind,緩存時機是在onLayout的過程中,並且用完即清空,裏面的view只是被detach,不會被remove,在onLayout時會使用;
  2. 二級緩存:mCacheViews
    mCacheViews也不需要重新bind,裏面的view是被remove過的;
  3. 三級緩存:mViewCacheExtension
  4. 四級緩存:mRecyclerPool

二、view查找過程
在RecyclerView的view不足時,需要addView,view的查找過程如下,一層層降級獲取可使用的view:

  1. 優先從mAttachedScrap列表中查找,查找的position必須和列表中某個holder的position完全一致,即:要查找的holder和該緩存裏面的某個holder達到完全一致的狀態;
  2. mCachedViews列表中查找,也需要position完全一致匹配。mCachedViews默認最大緩存爲2,當大於該值時,將holder緩存移至RecycledViewPool;
  3. mAdapter.hasStableIds()爲true時,否則轉4:從mAttachedScrap、mCachedViews列表中查找viewType相同的holder,在1、2都失敗的情況下,說明position完全匹配失敗,這時候需要找到viewType相同的holder緩存;
  4. 從RecycledViewPool裏面根據viewType查找緩存的holder。
    說明:RecycledViewPool針對每一種viewType有一個緩衝池,池子大小默認爲5,當某一種viewType的holder在RecycledViewPool中的緩存數量大於最大值時,會被丟棄;
  5. 緩存全部無法命中,則調用Adapter.createViewHolder新建holder。
發佈了17 篇原創文章 · 獲贊 25 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章