原文:Merge adapters sequentially with MergeAdapter
做者:Florina Muntenescu
譯者:Fly_with24java
MergeAdapter
是 recyclerview 1.2.0-alpha02
中提供的新類,它使您能夠順序組合多個 adapter,以在單個 RecyclerView 中顯示。 這使您能夠更好地封裝 adapter,而沒必要將許多數據源組合到單個 adapter 中,從而使它們集中並複用。android
一個用例是在 Header 或 Footer 中顯示列表加載狀態:當列表從網絡中檢索數據時,咱們想顯示一個進度條。 若是出現錯誤,咱們要顯示錯誤和重試按鈕。git
MergeAdapter
容許咱們按順序顯示多個 adapter 的內容。 例如,假設咱們有如下 3 個adapter:github
val firstAdapter: FirstAdapter = …
val secondAdapter: SecondAdapter = …
val thirdAdapter: ThirdAdapter = …
val mergeAdapter = MergeAdapter(firstAdapter, secondAdapter,
thirdAdapter)
recyclerView.adapter = mergeAdapter
複製代碼
recyclerView 將順序顯示每一個 adapter 中的 item網絡
使用不一樣的 adapter 可使您更好地區分列表的每一個順序部分。 例如,若是要顯示標題,則無需將與標題顯示相關的邏輯放在處理列表顯示的同一 adapter 中,而是能夠將其封裝在其本身的 adapter 中app
咱們的 Header/Footer 顯示進度或提示錯誤。 列表成功完成加載後,Header/Footer 不該顯示任何內容。 所以,可使用本身的 adapter 將其表示爲包含 0 或 1 個項目的列表:佈局
val mergeAdapter = MergeAdapter(headerAdapter, listAdapter, footerAdapter)
recyclerView.adapter = mergeAdapter
複製代碼
若是 Header/Footer 使用相同的佈局,ViewHolder
和 UI 邏輯(例如顯示進度以及顯示方式),則能夠僅實現一個 adapter 類並建立 2 個實例:一個用於 Header,一個用於 Footer動畫
對於完整的實現,請查看該 pull request,其中添加:ui
LoadState
顯示 0 或 1 個 item。 每次 LoadState
更改時,咱們都會通知您須要更改,插入或刪除該 item(請參見代碼)默認狀況下,每一個 adapter 都維護本身的 ViewHolder pool
,而且 adapter 之間不會複用。 若是多個 adapter 顯示相同的 ViewHolder
,咱們可能要在它們之間複用同一個實例。 咱們能夠經過使用 MergeAdapter.Config
對象來建立 MergeAdapter
來實現此目的,其中 isolateViewTypes = false
。 這樣,全部合併的 adapter 將使用相同的 view pool
。 在加載狀態 Header 和 Footer 示例中,兩個 ViewHolder
實際上將顯示相同的內容,所以咱們能夠重複使用它們google
⚠️ 若要支持不一樣的
ViewHolder
類型,應實現Adapter.getItemViewType
。 當您重複使用ViewHolder
時,請確保相同的 view 類型不會指向不一樣的ViewHolder
! 一種最佳實踐是將佈局 id 做爲 view 類型返回。
建議不要使用固定的 id 與 notifyDataSetChanged 一塊兒使用,而是建議使用 adapter 的特定通知事件,該事件爲 RecyclerView 提供有關數據集更改的更多信息。 這使 RecyclerView 能夠更有效地更新 UI 並具備更好的動畫。 若是您使用的是 ListAdapter,則在 DiffUtil 回調的幫助下,將在後臺爲您處理 notify 事件。 可是,若是確實須要使用 固定的 id,則 MergeAdapter.Config
爲固定的 id 提供 3 種不一樣的配置:NO_STABLE_IDS,ISOLATED_STABLE_IDS 和 SHARED_STABLE_IDS。 最後兩個要求您處理 adapter 中的 固定的 id。 請查看 StableIdMode 文檔以獲取有關其工做方式的更多信息
當 MergeAdapter
的 adapter 部分調用通知功能時,MergeAdapter
會在更新RecyclerView 以前計算新 item 的位置。
從 RecyclerView 的角度來看,notifyItemRangeChanged
表示 item 相同,只是內容有所更改。 notifyDataSetChanged
表示以前和以後之間沒有任何關係。 所以,咱們沒法將 notifyDataSetChanged
映射到 notifyItemRangeChanged
中
若是 adapter 調用 Adapter.notifyDataSetChanged
,則 MergeAdapter
還將調用Adapter.notifyDataSetChanged
,而不是 Adapter.notifyItemRangeChanged
。 與 RecyclerView 同樣,一般避免調用 Adapter.notifyDataSetChanged()
,而是選擇更精細的更新,或者使用自動執行此操做的 adapter 實現,例如 ListAdapter 或 SortedList
您過去可能曾經使用過 ViewHolder.getAdapterPosition
來獲取 ViewHolder
在 adapter 中的位置。 如今,由於咱們要合併多個 adapter,因此請使用 ViewHolder.getBindingAdapterPosition()
。 若是要獲取最後綁定 ViewHolder
的 adapter,則在共享 ViewHolder
的狀況下,使用 ViewHolder.getBindingAdapter()
若是要順序顯示不一樣類型的數據,這些數據將從封裝在其本身的 adapter 中受益,請開始使用 MergeAdapter
。 要對 ViewHolder pool
和 固定的 id 進行高級控制,請使用 MergeAdapter.Config
我是 Fly_with24