使用可觀察數據對象 [翻譯]

官方英文文檔:https://developer.android.google.cn/topic/libraries/data-binding/observability

一、介紹

觀察能力是指一個對象可以通知別人它的數據已經發生改變的能力。DataBinding庫允許你讓你的對象、字段、集合具備觀察能力。

普通對象可以用於DataBinding,但是它們不會自動通知UI它們發生改變了. DataBinding可以賦予對象在數據改變時通知其他對象的能力 。

二、可觀察字段(Observable Fields

當對象只有少量有效字段時,就沒有必要創建一個實現Observable接口的類了,對於這種情況,可以使用以下專用類來讓字段具備觀察能力。

  • ObservableBoolean
  • ObservableByte
  • ObservableChar
  • ObservableShort
  • ObservableInt
  • ObservableLong
  • ObservableFloat
  • ObservableDouble
  • ObservableParcelable

可觀察對象只有單個字段,基本類型版本在訪問時可以避免自動裝箱和自動拆箱,而要使用這一機制,可以如下創建public finalJava屬性,或者創建只讀read-onlyKotlin屬性

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

// kotlin
class User {
    val firstName = ObservableField<String>()
    val lastName = ObservableField<String>()
    val age = ObservableInt()
}

通過setget方法剛問字段值:

// kotlin 
user.firstName = "Google"
val age = user.age

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

Note:Android studio 3.1及以上版本中可以通過使用LiveData來替換可觀察字段,並且使用LiveData可以帶來額外的好處,具體看 這裏.

三、可觀察集合

一些應用需要使用動態數據結構來來存儲數據,可觀察集合允許通過key來訪問這些數據結構,如 ObservableArrayMap.

 // Kotlin
ObservableArrayMap<String, Any>().apply {
    put("firstName", "Google")
    put("lastName", "Inc.")
    put("age", 17)
}

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

而在佈局中的使用方法如下示例:

<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"/>

ObservableArrayListkey爲整型數據時非常有用,如下:

//Kotlin
ObservableArrayList<Any>().apply {
    add("Google")
    add("Inc.")
    add(17)
} 

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

對用在佈局中可以通過索引來訪問這個列表的數據,如下:

<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接口的類允許註冊的監聽器接收到它的字段數據發生改變的通知。

Observable接口包含註冊和移除監聽器的機制,但是我們需要決定什麼是時候發送通知,爲了方便開發,Databinding庫提供了BaseObservable類來實現這個監聽器註冊機制。繼承了BaseObservable的類負責在對象屬性改變時發送通知,當給get方法加上@Bindable註解,且在set方法中調用notifyPropertyChanged方法時,這個流程就完成了,如下示例:

// Java
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);
    }
}

// Kotlin
class User : BaseObservable() {

    @get:Bindable
    var firstName: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.firstName)
        }

    @get:Bindable
    var lastName: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.lastName)
        }
}

Data Binding會在模塊包生成一個叫做BR的類,它包含了用於數據綁定的資源ID@Bindable註解則會在編譯時在BR中生成一個entry。如果數據類仍不能改變,那麼可以通過PropertyChangeRegistry對象註冊和高效地通知監聽器。

關於 Bindable

@Bindable必須作爲get方法的註解,如下示例,注意到@Bindable({"firstName", "lastName"}}, 這裏可以綁定多個字段,而在這些字段中,當有一個字段被更新後,與之相關聯的字段(如這裏的name,它依賴於firstNamelastName)都會被視作垃圾數據而被更新。但是這並不意味會onPropertyChanged(Observable, int)會接收到因爲BR.name變成垃圾數據而觸發的通知,當且僅當綁定表達式(binding expressions)中包含name字段的情況纔會被視作垃圾數據並更新

@Bindable
 public void getFirstName() { return this.firstName; }

 @Bindable
 public void getLastName() { return this.lastName; }

 @Bindable({"firstName", "lastName"}}
 public void getName() { return this.firstName + ' ' + this.lastName; }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章