数据模型 任意POJO(简单java对象)都可以用于数据绑定.但是默认情况下,修改一个POJO的属性,并不会引发UI更新.databind真正的威力在于可以给予数据模型在数据发生变化时请求UI更新的能力.这里有3中不同的数据变更通知机制. Observable objects, observable fields, 和observable collections.
Observable objects 实现了Observable接口的类实例会允许bind过程中给它添加一个listener,用来监听这个实例属性的变化.
Observable接口定义了添加和移除listener的机制,但是开发者关心的只是数据变化发起的通知.为了方便开发者,基类BaseObservable被创建,用来自动完成listener添加机制.但是实现方依然有责任在数据发生变化时,发出通知.这里可以通过添加一个Bindable的注解在get方法上,并在set方法中来发出通知.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 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); } }
译者注,不写get/set方法,直接把注解加载成员变量上面也是可以的. 编译过程中,会在module package中生成BR类,Bindable注解在这个过程中会在BR类中生成一个变量. 如果您的数据类无法修改,则可以使用 PropertyChangeRegistry 来保存和通知改变事件。(此处不太懂)
ObservableFields 直接继承BaseObservable类可能有点麻烦.如果你的类只有一小部分属性需要变化并通知,你可以使用ObervableField及其相关类:ObservableBoolean, ObservableByte, ObservableChar, ObservableShort, ObservableInt, ObservableLong, ObservableFloat, ObservableDouble, and ObservableParcelable. ObervableFields是一个自身继承BaseObservable的对象,内部封装了一个基本对象,访问时并不会涉及封包解包操作.使用时,在数据对象中创建一个public final的属性即可:
1 2 3 4 5 6 7 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方法即可.
1 2 user.firstName.set("Google" );int age = user.age.get();
Observable Collections 有的应用中可能需要更加灵活的数据结构来存储数据.ObservableCollections支持使用key或者下标来访问这些数据. 当key为对象时,比如String,可以使用ObservableArrayMap:
1 2 3 4 ObservableArrayMap<String, Object> user = new ObservableArrayMap<>(); user.put("firstName" , "Google" ); user.put("lastName" , "Inc." ); user.put("age" , 17 );
然后在layout中可以通过key来访问数据
1 2 3 4 5 6 7 8 9 10 11 12 13 <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,然后通过下标来访问数据
1 2 3 4 ObservableArrayList<Object> user = new ObservableArrayList<>(); user.add("Google" ); user.add("Inc." ); user.add(17 );
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <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”/>