Data Binding 系列(四)可观察的数据对象

1,301 阅读2分钟

可观察的数据对象提供了当数据变化时通知其他对象的能力。Data Binding 库提供了使对象、字段和集合可观察的能力。

任何的传统对象都可以用于 Data Binding,但是这些对象数据发生变化时并不能通知 UI 更新。Data Binding 提供了使数据可观察的方法,就像 Listeners 一样,它提供了三种可观察的类:对象(objects)、字段(fileds)和集合(collections)。

当这些可观察的数据对象与 UI 绑定后,数据变化时会自动更新 UI

可观察的字段(observable fields

Data Binding 已经为我们写好了用于观察基础类型的类,它们都实现了 Observable 接口:

使用方法是,在 java 类中创建 public final 属性,在 kotlin 中创建只读属性,如下所示:

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

可以使用 get()set() 方法,访问这些可观察字段的值,如下所示:

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

可观察的集合

对于 key 是引用类型的时候,可以使用 ObservableArrayMap ,如下所示:

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

对于 key 是整型,可以使用 ObservableArrayList ,如下所示:

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 可以允许外界注册/移除监听器,但是变化通知的发送是由我们自己来控制的。为了方便我们开发,Data Binding 提供了 BaseObservable ,它默认实现了监听器的注册和移除,我们可以直接继承 BaseObservable ,只负责发送变化通知就行了。变化通知的发送,需要我们给类属性的 get() 方法加上 Bindable 注解,并在 set() 方法里调用 notifyPropertyChanged() 方法,示例如下:

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。