《Android》『DataBinding』- 如何透過 DataBinding 於 Android 中實現 MVVM 架構

《Android Developers 參考文獻》

➥DataBinding

 

《簡單介紹》

DataBinding 是最近才被運用在 Android 上的一種新的佈局方法,在傳統的 MVC 架構中,為了讓程式在開發與維護時,能夠更加簡單,我們盡力將程式的資料(Model)、邏輯控制(Control)以及介面(View)之間分開獨立,但在實作上,介面的顯示往往會隨著邏輯運算而必須被更動,不知不覺間卻又增加了兩者之間的複雜度。

bg2015020105

MVC 架構

為了解決上述所遇到的難題,我們透過 DataBinding 的方式,將一些會影響介面顯示的邏輯運算,直接寫在定義介面的 layout.xml 佈局檔中,如此一來,我們可以大幅的減少在程式碼中所必須定義與指向的介面元件 id,以及相關修改介面顯示的動作,進而降低介面設計與程式設計彼此的影響,這種模式我們稱作 MVVM (Model-View-ViewModel),Model 代表的是改變介面顯示的方法,View 代表的是介面顯示的視圖,ViewModel 則可以看成把這兩者綁定起來的接口,也就是改變介面顯示的邏輯。

bg2015020110

MVVM 架構

在傳統的 MVC 架構中,當我們需要改動一個介面顯示的值時,我們必須找到代表該元件的 id (findViewById),接著於程式碼中更新其內容的值,但若是在 MVVM 的架構下,因為我們已經綁定了判斷介面改動的邏輯與視圖,只要邏輯的部分有所更動,視圖就會自動更新。

 

《宣告 & 使用方式》

單是看上面的介紹,感覺還是很抽象,以下就直接透過程式碼片段的方式,說明 DataBinding 的基本用法。

➥ Android 開發環境需求

➥ DataBinding 的基本用法

Android 開發環境需求

要使用 DataBinding,首先我們必須將 Android Studio 版本升級到 1.3 以上,這邊建議升到目前最新版本(也就是Android Studio 2.0),因為在 2.0 的版本,於開發環境中才開始支援自動完成與提示的輔助功能。

在確認版本以後,接下來我們必須修改在 Gradle Scripts 底下的 build.gradle (Module: app) 檔案,在裡面加入如下資訊 –

build.gradle (Module: app)

將 databinding 下的 enable 設成 true 即可。

 

DataBinding 的基本用法

DataBinding 的使用可以按照架構分成三個部份來探討,條列整理如下 –

➥ View 層 – 介面顯示的視圖

➥ Model 層 – 用來改動介面顯示的邏輯

➥ ViewModel 層 – 把這兩者綁定起來的接口

 

View 層

首先來介紹 View 層,在使用 DataBinding 時,我們必須先改寫原本的 layout.xml 佈局檔,假設我們原本的佈局檔定義如下 –

未使用 DataBinding 的 activity_main.xml

改為使用 DataBinding 所定義的介面佈局檔如下 –

使用 DataBinding 的 activity_main.xml

首先我們將需要使用 DataBinding 的介面佈局檔以 <layout></layout> 標籤包起來(也可以是佈局檔中的一部分),並在其中定義了 <data></data> 標籤,在裡面我們接著定義 <variable></variable> 標籤,其中帶有兩個屬性,分別是 name type,type 用來告知這個 variable 所代表的類別(或者是基本型別),而 name 則代表了這個類別在這份 activity_main.xml 佈局檔中的變數名稱。

當定義好名稱以後,便可以在 TextView 介面元件中設定我們想讓它隨著邏輯更動的相關屬性,這邊把用到的屬性條列說明如下 –

android:text=”@{MyDataObjModel1.alias}”

表示這個 TextView 介面元件的顯示文字會根據 MyDataObjModel1.alias 的值做更動。

android:background=”@{MyDataObjModel1.backgroundColor}

表示這個 TextView 介面元件的背景顏色會根據 MyDataObjModel1.backgroundColor 的值做更動。

android:onClick=”@{MyHandlerModel.onClick}”

表示這個 TextView 介面元件的點擊事件會根據 MyHandlerModel.onClick 方法執行。

android:padding=”@{largeModel?@dimen/largePadding:@dimen/smallPadding}”

表示這個 TextView 介面元件的 padding 屬性會根據 largeModel 布林值做選擇,為 true 則選擇 largePadding,false 則選擇 smallPadding。


※系統環境會自動生成 DataBinding 的類別與變數方法

這邊要提醒的是,當我們將整個 activity_main.xml 佈局檔以 <layout></layout> 標籤包起來後,系統會自動根據所包覆的佈局檔命名建立一個 DataBinding 的類別。

以 activity_main.xml 命名為例,系統便會自動建立一個名為 ActivityMainBinding 的類別。

接著,在定義每個 <variable></variable> 標籤的時候,系統亦會自動透過我們宣告的每個變數的 name 名稱,將該變數的set、get 方法在 ActivityMainBinding 的類別中建立起來,透過這兩個方法,我們可以在 MainActivity 中直接修改或取得這些變數的值,省略了繁瑣的 findViewById 定義。

以前面的例子來說,當我們將 variable name 設定為 MyDataObjModel1 以後,系統便會根據這個名稱,在 ActivityMainBinding 的類別中自動建立 getMyDataObjModel1() 與 setMyDataObjModel1() 這兩個方法,功能為取得與儲存目前設定好的 MyDataObjModel1 物件。


 

Model 層

接著下面我們來看 Model 層,也就是在上面介面佈局檔中所使用到的 MyDataObjModel1MyDataObjModel2MyHandlerModel 以及 largeModel 類別,其中MyDataObjModel1 與 MyDataObjModel2 我們分別用兩種不同的類別宣告方式,但兩者 DataBinding 的效果是一樣的,條列整理如下 –

➥ MyDataObjModel1 類別 – Observable Objects 用法

➥ MyDataObjModel2 類別 – Observable Fields 用法

➥ HandlerModel 類別 – 處理 onClick 事件

MyDataObjModel1.java

MyDataObjModel1 類別繼承了 BaseObservable 類別,在其中我們定義了兩個參數,分別是 text 以及 color,並定義了針對這兩個參數的 get 與 set 方法,這邊要注意的是,我們在 get 方法前面有標註了 @Bindable,這代表著這個 get 方法定義完成以後,系統會根據這個方法的名稱自動產生取值的參數名稱(getAlias() 會自動產生 alias 參數名稱),BR 類亦會自動生成(名字與參數名稱一致);set 方法則可以由我們自行定義,並在 set 方法的最後加入 notifyPropertyChanged(BR.title) 方法通知 View 更新。

※ BR 類的名稱會根據標註了 @Bindable 的 get 方法名稱來生成,以此例來說,我們分別標註了 getAlias() 與 getBackgroundColor() 兩個方法,因此在 BR 類中就會自動生成 BR.alias 以及 BR.backgroundColor,在 layout 中 Model 的取值參數名稱亦會自動生成為 alias 以及 backgroundColor。

MyDataObjModel2.java

透過 MyDataObj2 類別的這種宣告方式,我們可以更快的定義好參數,其他常用的型別如下 –

ObservableBoolean、ObservableByte、ObservableShort、ObservableInt、

ObservableLong、ObservableChar、ObservableFloat、ObservableDouble、

ObservableParcelable、ObservableArrayMap、ObservableArrayList

MyHandlerModel.java

自訂一個 MyHandler 類別,以實作自訂的 onClick() 事件。

 

ViewModel 層

最後來看 ViewModel 層,也就是寫在這個程式主要的 MainActivity.java 中之邏輯判斷。

MainActivity.java

在定義好 View 層與 Model 層以後,我們需要把兩者連結起來,使得當在 Model 層中的數據變化時,View 層會自動做出更新。

簡單的說,我們利用系統自動生成的 Binding 類別來儲存所有的介面元件,但是將控制介面該如何顯示的 get、set 方法寫在 Model 層(其中 get 方法會由系統在使用到 notifyPropertyChanged 時自動呼叫),最後,我們在 ViewModel 層中,透過此層本身的邏輯判斷,使用 Model 層中定義好的 set 方法來改變介面顯示的數值或者樣式。

賽肥膩膩

我們是低調到不行的肥膩夫妻檔,一路上一邊吵鬧一邊記錄著生活大小事,最近迷上了宅在家追劇,希望能透過文字將所有看過的影集好好紀錄,整理成屬於我們自己的回憶資料庫。

上 / 下一篇文章

臉書留言

一般留言

  1. ViewModel 不應該寫在activity裡
    mvvm一開始的用意就是避免寫出巨大的activity class

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *