RecyclerView的基本設計結構

2021-09-11 10:15:17 字數 4356 閱讀 3182

下面這張圖是我擷取的recyclerview的structure:

本文著重看:viewholderadapteradapterdataobservablerecyclerviewdataobserverlayoutmanager、、recyclerrecyclerpool。 從而理解recycledview的大致實現原理。

先用一張圖大致描述他們之間的關係,這張圖是adapter.notifyxx()recyclerview的執行邏輯涉及到的一些類:

對於adapter來說,乙個viewholder就對應乙個data。它也是recycler快取池的基本單元。

class viewholder 

複製**

上面我列出了viewholder最重要的4個屬性:

它的工作是把dataview繫結,即上面說的乙個data對應乙個viewholder。主要負責viewholder的建立以及資料變化時通知recycledview。比如下面這個adapter:

class ******stringadapter(val datasource: list, val context: context) : recyclerview.adapter() 

}override fun oncreateviewholder(parent: viewgroup, viewtype: int) = ******vh(******strin**iew(context))

override fun getitemcount() = datasource.size

override fun getitemviewtype(position: int) = 1

override fun notifydatasetchanged

()

}複製**

即:

它引用著乙個資料來源集合datasourcegetitemcount()用來告訴recyclerview展示的總條目

它並不是直接對映data -> viewholder, 而是data position -> data type -> viewholder。 所以對於viewholder來說,它知道的只是它的view typeadapter是資料來源的直接接觸者,當資料來源發生變化時,它需要通知給recyclerview。這裡使用的模式是觀察者模式adapterdataobservable是資料來源變化時的被觀察者。recyclerviewdataobserver是觀察者。 在開發中我們通常使用adapter.notifyxx()來重新整理ui,實際上adapter會呼叫adapterdataobservablenotifychanged():

public void notifychanged

() }

複製**

邏輯很簡單,即通知observer資料發生變化。

它是recycledview用來監聽adapter資料變化的觀察者:

public void onchanged

() }

複製**

它是recyclerview的布局管理者,recyclerviewonlayout時,會利用它來layoutchildren,它決定了recyclerview中的子view的擺放規則。但不止如此, 它做的工作還有:

測量子view

對子view進行布局

對子view進行**

子view動畫的排程

負責recyclerview滾動的實現

...對於layoutmanager來說,它是viewholder的提供者。對於recyclerview來說,它是viewholder的管理者,是recyclerview最核心的實現。下面這張圖大致描述了它的組成:

final arraylistmattachedscrap = new arraylist<>();

arraylistmchangedscrap = null;

複製**

相信你在許多recyclerviewcrash log中都看到過這個單詞。它是指viewrecyclerview布局期間進入分離狀態的子檢視。即它已經被deatach(被標記為flag_tmp_detached狀態)了。這種view是可以被立即復用的。它在復用時,如果資料沒有更新,是不需要呼叫onbindviewholder方法的。如果資料更新了,那麼需要重新呼叫onbindviewholder

mattachedscrapmchangedscrap中的view復用主要作用在adapter.notify***時。這時候就會產生很多scrap狀態的view。 也可以把它理解為乙個viewholder的快取。不過在從這裡獲取viewholder時完全是根據viewholderposition而不是item type。如果在notifyxx時data已經被移除掉你,那麼其中對應的viewholder也會被移除掉。

可以把它理解為recyclerview的一級快取。它的預設大小是3, 從中可以根據item type或者position來獲取viewholder。可以通過recyclerview.setitemviewcachesize()來改變它的大小。

它是乙個可以被復用的viewholder快取池。即可以給多個recycledview來設定統一個recycledviewpool。這個對於多tab feed流應用可能會有很顯著的效果。它內部利用乙個scrapdata來儲存viewholder集合:

class scrapdata 

sparsearraymscrap = new sparsearray<>(); //recycledviewpool 用來儲存viewholder的容器

複製**

乙個scrapdata對應一種typeviewholder集合。看一下它的獲取viewholder和儲存viewholder的方法:

//存

public void putrecycledview(viewholder scrap)

//取private scrapdata getscrapdatafortype(int viewtype)

return scrapdata;

}複製**

以上所述,是recycledview最核心的組成部分(本文並沒有描述動畫的部分)。

歡迎關注我的android高階計畫。看更多乾貨

RecyclerView的簡單使用

recyclerview 和 listview 一樣都是通過維護少量的view來展示大量的資料,不同的是recyclerview提供了一種插拔式的體驗,高度解耦,同時使用起來更加靈活。recyclerview可以通過設定layoutmanager oritation itemanimation it...

關於RecyclerView的Adapter封裝

專案開發中會涉及到很多列表的頁面。如果每個頁面都寫乙個adapter,我們估計會瘋掉。我現在的目的就是在保證質量的同時要寫更少的 所以,封裝唄。recyclerview有自己的adapter和檢視管理。我們只需要把例項化時要傳入的引數泛型抽象,對不同的view實現不同的獲取與設定內容的方法即可。ad...

RecyclerView 的使用流程

一 加入依賴 使用 as 自帶的依賴管理工具加入recyclerview的依賴,注意和和編譯版本號一致 二 在布局檔案中加入 recyclerview控制項 android id id main recylist android layout width wrap content android l...