DataBinding(五)自动更新
虽然使用普通的Java对象就可以把数据绑定到UI界面,但是当数据变动时,UI却不会及时更新,所以DataBinding提供了observable objects、observable fields、observable collections来达到自动更新的效果。
observable objects
如果一个类实现了android.databinding.Observable接口,则DataBinding会绑定一个监听器来监听这个类的属性变化,DataBinding为了方便我们使用,提供了一个实现类BaseObservable。BaseObservable接口帮我们进行了监听器的绑定和移除,我们只要自己进行更新就可以了。对于getter使用@Bindable注解来生成BR.propertName
字段,然后setter中调用notifyPropertyChanged(BR.propertName)
语句来通知更新。
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);
}
}
observable fields
对于自定义类可以通过以上方式进行设置,同时DataBinding也提供了另一种比较简便的方式,可以对单一字段进行包装,自动更新该字段:
private static class User {
public final ObservableField<String> firstName = new ObservableField<>();
public final ObservableField<String> lastName = new ObservableField<>();
public final ObservableInt age = new ObservableInt();
}
其他可以使用的包装类包括:ObservableBoolean、ObservableByte、ObservableChar、ObservableShort、ObservableLong、ObservableFloat、ObservableDouble、ObservableParcelable。
赋值及取值使用set和get方法:
user.firstName.set("Google");
int age = user.age.get();
ObservableField还有另一种用法,即通过<include />
传递属性,传递的属性是ObservableField<String>
,然后被include的文件中使用String接收。
例如:
<layout>
<data>
<variable
name="user"
type="com.example.testdatabinding2.User"/>
</data>
<include
layout="@layout/extra"
app:firstName="@{user.firstName}"/>
</layout>
<?xml version="1.0" encoding="utf-8"?>
<layout>
<data>
<variable
name="firstName"
type="String"/>
</data>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{firstName}"/>
</LinearLayout>
</layout>
observable collections
当使用了集合数据时,如果key是引用类型,可以使用ObservableArrayMap包装类:
ObservableArrayMap<String, Object> user = new ObservableArrayMap<>();
user.put("firstName", "Google");
user.put("lastName", "Inc.");
user.put("age", 17);
<!-- XML -->
<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是int类型,则可以使用ObservableArrayList包装类:
ObservableArrayList<Object> user = new ObservableArrayList<>();
user.add("Google");
user.add("Inc.");
user.add(17);
<!-- XML -->
<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"/>