Android Recyclerview ConcatAdapter AndroidX Jetpack

Android ConcatAdapter - 組合多個資料來源

Fox Tsai 2021/06/16 17:47:47
3096

 

 

Android ConcatAdapter - 組合多個資料來源

 

 

前言

 

開發 APP 時,在需要顯示大量資訊但顯示項目外觀有著些許不同或是多個區塊時,常常會遇到一個問題是:『這個頁面我要不要重複使用內容?』

 

數量少的時候可能會選擇使用 ScrollView 然後內容寫死,數量多的時候可能會用多個 Recyclerview 或是透過 ViewType 區分並且混用多個 ViewHolder,不過在這個情況下的Adapter通常需要塞入大量的程式碼處理不同類型的 itemView

 

針對這類有順序且區塊分明的內容,Google 推出了新元件 ConcatAdapter,並在今年四月 Recyclerview 推出 1.2.0 版時,正式包含在套件裡面。

 

ConcatAdapter 顧名思義,就是將 Adapter 連接起來的 Adapter,允許你在同一個 Recyclerview 同時使用多個 Adapter

 

 

 

內容

 

使用方式

-       最低版本限制

功能實作

-       內容分類

-       建立ViewHolder

-       建立Recyclerview Adapter

-       使用ConcatAdapter

-       關於ConcatAdapter.ConfigisolateViewTypes

結語

參考資料

範例原始碼

 

 

使用方式

 

 

使用上僅需跟 Recyclerview 同時加入,並指定版本為 1.2.0 以上,請在 app build.gradle 檔案的 dependencies 區塊內添加:

 

implementation("androidx.recyclerview:recyclerview:1.2.0")

  

 

最低版本限制

 

 

根據 CommonsWare 所維護的 AndroidX 套件資訊列表,Recyclerview 1.2.0 套件的 minSdkVersion (api level) 14,也就是 Android 4.0

 

 

功能實作

 

 

底下我們會實作一個 Demo APP,假設有個畫面需求如上圖所示,顯示產品圖片、產品名稱、產品價格、產品規格以及特色說明。圖上的做法是完全使用 ScrollViewLinearLayoutTextView ImageView 寫死內容,對於規格已經相當確定且不太會變動的頁面使用這樣的方法尚可接受,不過如果如果要保持擴充彈性建議還是不使用這樣的方法製作,一方面是 xml layout 檔案內會相當雜亂冗長,接下來我們會將這個畫面改成使用 ConcatAdapter 實作。

 

 

 

內容分類

 

 

畫面上可以很簡單分出幾個區塊,包含只有單一項目的產品圖片、產品標題 (名稱與價格),還有比較多個項目的產品規格與特色說明,這邊就直接拆成 4 Adapter 去負責個別區塊的內容。

 

 

 

建立 ViewHolder

 

 

商品圖片就只放入一個 ImageView 顯示商品圖片。

 

 

標題部分放上產品名稱跟價格文字。

 

 

規格部分只放一組文字。

 

 

特色說明部分有一張圖片跟說明文字。

 

 

 

建立 Recyclerview Adapter

 

 

首先為四個區塊分別產生對應的 Adapter ViewHolder

 

 

資料來源直接使用 arrays 資源檔處理,標題部分算是比較偷吃步,直接用一個項目包含兩個資料,底下的 Adapter 因此可以再簡化。

 

 

首先建立商品圖片來源 ProductImageAdapter,圖片部分使用字串取回圖片 Resource ID再進行套用

 

 

接著建立產品標題來源 ProductTitleAdapter

 

 

建立產品規格來源 ProductSpecAdapter

 

 

建立產品特色來源 ProductFeatureAdapter

 

 

使用 ConcatAdapter

 

 

ConcatAdapter 的使用方法其實相當簡單,可以直接傳入 List<Adapter>,或是將 Adapter 一個接一個帶入。

 

 

回到專案原始碼,新增一個 ProductActivityxml layout 部分只擺上一個填滿畫面的 Recyclerview

 

 

接著使用字串陣列資源建立每個區塊的 Recyclerview Adapter 後,新增一個 ConcatAdapter 並按照畫面上的順序將每一個區塊的 Adapter 填入,並且指定給 Recyclerview 使用。

 

 

 

執行後就可以看到顯示後的結果了,跟直接寫死的畫面基本上一樣,但主要的 layout 上僅需使用一個 Recyclerview

 

 

 

關於 ConcatAdapter.Config isolateViewTypes

 

 

還記得前面圖片中的 ConcatAdapter 建構子嗎,其中兩個前面講過,另外兩個看起來很像但是前面多了一個 ConcatAdapter.Config 的設定參數。

 

 

 

官方文件裡面可以看到 Config 裡面的成員包含一個 Boolean isolateViewTypes,這個值主要用來控制各個 Adpater itemViewType 是否互相隔離,跟字面上的意思一樣,預設為開啟。

 

 

 

當不開啟 isolateViewTypes 時,ConcatAdapter 內的每一個 Adapter 成員都有各自的 ViewType,舉例來說,第 1 個跟第 4 Adapter 的類別都是 RedAdapter,假設他們 itemView 的 ViewType 1,經過 ConcatAdapter 處理後他的 itemView 會被視為不同的 ViewType,也就是變成有 4 ViewType

 

 

 

由於 Recyclerview 的快取空間內,不同的 ViewType 會各自獨立,因此在上述情況下,明明 RedAdapter 用的是一樣的 ViewType,但他們無法共用快取。

 

 

預設情況下將 isolateViewTypes 設為 true 可以避免因為混用快取產生的風險,但如果無論如何都要進行共用,在 Adapter 內需要實作 getItemViewType 方法。

 

 

 

在各個 Adapter 實作完 getItemViewType 方法後,接著利用 ConcatAdapter.Config.Builder 產生設定並在建立 ConcatAdapter 時帶入即可,其實就等同於以往在單一 Adapter 中使用多個 item layout 的使用方式,差別在於列表項目位置的判斷由 ConcatAdapter 自行處理掉了。

 

 

 

結語

 

利用新的 ConcatAdapter,我們可以有效率的整合多個資料來源,完成一個擁有多個內容區塊的列表頁,避免單一 Adapter 搭配多個 ViewHolder 造成 Adapter 程式碼不好維護的問題,也能減少主要畫面 xml layout 的複雜度。進行 Adapter 拆分的同時也增加了畫面重複使用上的靈活度。然而這個元件也不是萬能的,設計上會比較適合沒有不同 itemView 交錯顯示的情境,遇到 APP 設計擁有較長的詳細資訊頁面,可以考慮使用這個新的元件來取代 ScrollView 或是多個 RecyclerView 的作法。

 

 

 

參考資料

 

Recyclerview | Android Developers

https://developer.android.com/jetpack/androidx/releases/recyclerview#recyclerview-1.2.0

 

ConcatAdapter | Android Developers

https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/ConcatAdapter

 

ConcatAdapter.Config | Android Developers

https://developer.android.com/reference/kotlin/androidx/recyclerview/widget/ConcatAdapter.Config

 

AndroidX Tech: androidx.recyclerview:recyclerview

https://androidx.tech/artifacts/recyclerview/recyclerview/1.2.0

 

Concatenate adapters sequentially with ConcatAdapter

https://medium.com/androiddevelopers/merge-adapters-sequentially-with-mergeadapter-294d2942127a

 

Android新發布的ConcatAdapter使用教程

https://juejin.cn/post/6962754669756022791

 

 

範例原始碼

GitHub

https://github.com/foxtsai2333/ConcatAdapterDemo

 

 

 

 

 

 

Fox Tsai