前言

可觀察性(Observability)是指一個物件具有當其數據發生變化時通知其他元件的能力。
Data Binding Library讓物件,欄位,集合具有可被觀察的能力
任何的 POJO 都可以使用於 Data Binding,但修改該物件時並不會讓 UI 也跟著更新。 Data Binding 可為數據對象(data object)提供在其數據更改時通知其他對象(稱為偵聽器)的能力。
可觀察類別(observable class)有 3 種類型,objects,fields,collections
當上列3種可觀察類別的物件綁定了 UI,且物件的屬性(property)發生變化時,UI 將會自動更新。
 

Observable fields

因為去建立實作 Observable 介面的類別需要一些額外工作,因此若開發者僅有少量的屬性其實是不值得的,在這種情況下可以使用一般性可觀察類別,如下

ObservableBoolean ObservableByte ObservableChar ObservableShort
ObservableInt ObservableLong ObservableFloat ObservableDouble
ObservableParcelable

 
Observable fields 是具有單一欄位的自包含可觀察物件,使用方式為建立一個 public final 屬性,如下

private static class User {
    public final ObservableField<String> firstName = new ObservableField<>();
    public final ObservableField<String> lastName = new ObservableField<>();
    public final ObservableInt age = new ObservableInt();
}

要存取數值,使用 set 和 get 方法如下

user.firstName.set("Google");
int age = user.age.get();

注意: Android Studio 3.1 或更高的版本可讓開發者以 LiveData objects 代替 observable fields,可提供額外的好處。參考 Use LiveData to notify the UI about data changes
 

Observable collections

有些 App 使用動態資料結構來持有數據,observable collections 為提供這些動態資料結構。
ObservableArrayMap 用於當鍵值為參考型別時特別有用,如下

ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);

在 layout 檔案中,map 使用如下

<data>
    <import type="android.databinding.ObservableMap"/>
    <variable name="user" type="ObservableMap<String, Object>"/>
</data>
…
<TextView
    android:text="@{user.lastName}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView
    android:text="@{String.valueOf(1 + (Integer)user.age)}"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

ObservableArrayList 則適用於當鍵值為 integer 時,如下

ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
user.add(17);

在 layout 檔案中,list 使用如下

<data>
    <import type="android.databinding.ObservableList"/>
    <import type="com.example.my.app.Fields"/>
    <variable name="user" type="ObservableList<Object>"/>
</data>
…
<TextView
    android:text='@{user[Fields.LAST_NAME]}'
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>
<TextView
    android:text='@{String.valueOf(1 + (Integer)user[Fields.AGE])}'
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"/>

 

Observable objects

當類別實作了 Observable 介面便可提供註冊監聽器,該監聽器可讓想觀察的元件可取得通知。
Observable 介面具有加入和移除監聽器的機制,但開發者必須決定何時送出通知。為了讓過程更簡單,Data Binding Library 提供了 BaseObservable 類別,該類別實作了監聽器註冊機制。
當屬性發生變化時,實作 BaseObservable 的類別便負責通知。透過在 getter方法加入 Bindable 註釋,並在 setter 方法呼叫 notifyPropertyChanged 方法,如下

private static class User extends BaseObservable {
    private String firstName;
    private String lastName;
    @Bindable
    public String getFirstName() {
        return this.firstName;
    }
    @Bindable
    public String getLastName() {
        return this.lastName;
    }
    public void setFirstName(String firstName) {
        this.firstName = firstName;
        notifyPropertyChanged(BR.firstName);
    }
    public void setLastName(String lastName) {
        this.lastName = lastName;
        notifyPropertyChanged(BR.lastName);
    }
}

 
Data Binding 會在 module package 產生一個 BR 的類別,該類包含用於數據綁定的資源的 ID。
Bindable 註釋在編譯期間會產生一個 entity 到 BR 類別。
如果無法更改 data class 的 base class,則可以使用 PropertyChangeRegistry 實現 Observable 接口,以有效地註冊和通知監聽器。