下面這張圖是我擷取的recyclerview的structure:
本文著重看:viewholder
、adapter
、adapterdataobservable
、recyclerviewdataobserver
、layoutmanager
、、recycler
、recyclerpool
。 從而理解recycledview
的大致實現原理。
先用一張圖大致描述他們之間的關係,這張圖是adapter.notifyxx()
時recyclerview
的執行邏輯涉及到的一些類:
對於adapter
來說,乙個viewholder
就對應乙個data
。它也是recycler快取池
的基本單元。
class viewholder
複製**
上面我列出了viewholder
最重要的4個屬性:
它的工作是把data
和view
繫結,即上面說的乙個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
()
}複製**
即:
它引用著乙個資料來源集合datasource
getitemcount()
用來告訴recyclerview
展示的總條目
它並不是直接對映data -> viewholder
, 而是data position -> data type -> viewholder
。 所以對於viewholder
來說,它知道的只是它的view type
adapter
是資料來源的直接接觸者,當資料來源發生變化時,它需要通知給recyclerview
。這裡使用的模式是觀察者模式
。adapterdataobservable
是資料來源變化時的被觀察者。recyclerviewdataobserver
是觀察者。 在開發中我們通常使用adapter.notifyxx()
來重新整理ui,實際上adapter
會呼叫adapterdataobservable
的notifychanged()
:
public void notifychanged
() }
複製**
邏輯很簡單,即通知observer
資料發生變化。
它是recycledview
用來監聽adapter
資料變化的觀察者:
public void onchanged
() }
複製**
它是recyclerview
的布局管理者,recyclerview
在onlayout
時,會利用它來layoutchildren
,它決定了recyclerview
中的子view的擺放規則。但不止如此, 它做的工作還有:
測量子view
對子view進行布局
對子view進行**
子view動畫的排程
負責recyclerview
滾動的實現
...對於layoutmanager
來說,它是viewholder
的提供者。對於recyclerview
來說,它是viewholder
的管理者,是recyclerview
最核心的實現。下面這張圖大致描述了它的組成:
final arraylistmattachedscrap = new arraylist<>();
arraylistmchangedscrap = null;
複製**
相信你在許多recyclerview
的crash log
中都看到過這個單詞。它是指view
在recyclerview
布局期間進入分離狀態的子檢視。即它已經被deatach
(被標記為flag_tmp_detached
狀態)了。這種view
是可以被立即復用的。它在復用時,如果資料沒有更新,是不需要呼叫onbindviewholder
方法的。如果資料更新了,那麼需要重新呼叫onbindviewholder
。
mattachedscrap
和mchangedscrap
中的view復用主要作用在adapter.notify***
時。這時候就會產生很多scrap
狀態的view
。 也可以把它理解為乙個viewholder
的快取。不過在從這裡獲取viewholder
時完全是根據viewholder
的position
而不是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
對應一種type
的viewholder
集合。看一下它的獲取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...