小而美的android adapter庫設計:支援MultiType | 掘金技術徵文

LemonYang發表於2016-12-16

目前這個專案已經開源到GitHub上面,歡迎大家關注
github.com/lemon-yang/…

android data binding library為我們提供了一個頁面與資料繫結的技術,尤其是android gradle plugin在2.2的版本之後,更是開始支援了雙向繫結以及lambada表示式,使得data binding的技術更加成熟,而將data bingding技術結合的mvvm設計結構也越來越得到更多的關注。在前面我的文章裡面,已經從原始碼的角度,講述了data binding庫的一些實現細節。現在結合data binding的技術實現一個adapter庫。

宣告:這個庫是在看了GitHub上面的一個開源專案binding-collection-adapter,然後結合自己的理解以及一些實際的經驗進行了優化和程式碼整體結構的調整。對於原始碼中優秀的工具類,我都沒有修改,按照原來的進行保留,並在檔案頭標明瞭檔案的出處。

整體功能描述

目前已經完成的功能:

  1. 支援在列表中裝載多種viewType的item。每個item對應一種佈局檔案以及一種ViewModle;
  2. 基於data binding庫設計,因此支援通過data binding技術(在XML檔案中配置)完成adapter的構建、資料載入以及其他data binding相應的技術實現;
  3. 支援在item的view檢視被data binding構建之後,對view檢視執行更多的配置操作。比如當item是一個圖示的時候,可能需要對圖示進行更多自定義的屬性配置。這時候可以通過data binding的註解技術實現(如果你很熟悉data binding的話),也可以通過decorator物件的介面回撥進行設定。
  4. 支援在data bingding的檢視和資料繫結之後,接收回撥,執行額外的操作;
  5. 實現了ListView、ViewPager、RecyclerView、ExpandableListView對應的adapter

目前還不完善的功能;

  1. 當你使用的是RecyclerView的時候,只能通過ViewHolder的factory構建自己的ViewHolder例項,並在ViewHolder中對view進行自定義配置,不能使用decorator物件開放的介面進行前置的檢視配置
  2. adapter當中的ViewDataBinding物件還不支援自定義的DataBindingComponent
  3. 其他可能需要但還沒被支援的屬性。。。

程式碼整體類圖

小而美的android adapter庫設計:支援MultiType | 掘金技術徵文

程式碼設計概述

上面的類圖基本上描述了程式碼中的結構,用兩個表示式闡述整個庫的功能實現就是:

adapter = ViewManager + ViewModle + Factory
ViewModle = Decorator + model(data)

ViewManager

ViewManager的設計初衷其實就是為了管理adapter需要裝載的各種item的樣式。每個adapter在初始化的時候都必須構建一個ViewManager的例項,這個ViewManager的例項標識了這個adapter需要載入的item的全部型別。

在庫當中,我將每個item抽象成了一個ItemView的物件, 主要包含了兩個屬性,一個是對應的佈局檔案ID,一個是item所繫結的data的索引值,也就是data binding中BR.java當中的值。而ViewManager則封裝了對ItemView的操作邏輯,使得item檢視選擇對外部是透明的。

ViewManager當中核心的邏輯就只有兩個部分:

  • 通過ViewManager的內部類Builder構建ViewManager例項的時候的put()方法。所有adapter需要支援的item型別都應該使用這個方法進行新增;
  • ViewManager當中的select()方法,主要是根據當前需要佈局的item型別,選擇載入合適的佈局檔案以及資料繫結;

另外ViewManager當中還包含了一個 NO_VARIABLE_BINDING 的常量值,當item不需要進行資料繫結的時候,可以使用這個標誌位進行標識。

Decorator

當我們使用data binding技術之後,data binding庫會自動的為我們初始化檢視,並且將資料與檢視進行繫結。但是很多時候,當我們使用的是一些複雜的item檢視型別的時候,我們需要對item裡面的檢視進行很多的配置操作。比如說我們在item當中載入的是一個圖示的時候,我們需要對圖示進行很多的屬性配置。這種情況下,如果純粹的依賴data binding的話,可能需要我們通過註解@BindAdapter完成相應的設定。如果不習慣這種做法的話,我們這個時候就可以使用decorator物件了。

Decorator是一個介面,包含兩個介面方法:

  • void onViewCreated(ViewDataBinding dataBinding);

這個方法會在檢視被data binding庫載入之後回撥

  • void onDataBinded(ViewDataBinding dataBinding);

這個方法會在檢視與資料繫結之後被回撥。

目前的實現中,ViewModle可以通過依賴注入增加這個介面的實現,而ViewModle物件是我們list裝載的item資料內容。也就是說每個item其實都具備一個Decorator的實現。當我們需要對item的檢視進行更多的配置的時候,就可以實現這個介面,並注入到我們的ViewModle裡面。

ViewModel

我們庫當中的list裝載的內容要求都是ViewModel的子類。也就是說我們需要將實際應用的model再進行封裝一層。
在庫當中的實現,我還是通過依賴注入將model(data)資料注入到ViewModel當中,而且我們可以往ViewModel注入更多的資料,也可以將一些互動的事件的實現在ViewModel當中。

Factory

庫當中的所有的adapter都實現了對應的工廠介面方法,我們可以通過實現工廠方法返回我們需要的自定義的adapter型別。預設都會提供一個DEFAULT的工廠,返回對應的adpter的基類。

AnnotationController

這個類是庫當中處理data binding相關注解的實現中樞。庫提供了通過在XML當中配置屬性,完成adpter的構建以及資料繫結的操作。如果你很熟悉data binding的使用方法的話,你可以通過新增對應的XML屬性設定就可以完成adapter的繫結了,非常的簡單快捷。如果你不熟悉這樣的方式,也可以使用傳統的在java程式碼中進行例項化和設定操作。

願景

目前這個庫的設計還比較初期,功能也只是完成了幾本覆蓋,並且因為是基於data binding技術設計的,因此專案當中必須在gradle當中開啟data binding的開關才可以。接下來會針對實際應用中的需求不斷完善這個庫的功能。

另外data binding在專案中只是負責了資料與檢視繫結的操作,對於庫當中其他的核心功能以及整個庫的架構是沒有強耦合的,因此我們完全可以通過開放資料繫結的邏輯介面方法,就能夠實現一個不依賴data binding的adapter庫。

目前這個專案我已經開源到GitHub上面,有興趣的同學可以star一下,也可以歡迎fork這個倉庫,一起改進。DataBindingAdapter.

如果你喜歡這篇文章,歡迎收藏。也歡迎你關注我,一起討論更多的問題,感謝你寶貴的時間閱讀這篇文章,謝謝!

掘金技術徵文活動

相關文章