Observable 对象
实现android.databinding.Observable接口的类可以允许附加一个监听器到Bound对象以便监听对象上的所有属性的变化。
Observable接口有一个机制来添加和删除监听器,但通知与否由开发人员管理。为了使开发更容易,Android 原生提供了已经封装好的一个类 - BaseObservable,并且实现了监听器的注册机制。
Data实现类依然负责通知当属性改变时。这是通过指定一个Bindable注解给getter以及setter内通知来完成的。
|
|
BR 是编译阶段生成的一个类,功能与 R.java 类似,用 @Bindable 标记过 getter 方法会在 BR 中生成一个 entry。
通过代码可以看出,当数据发生变化时还是需要手动发出通知。 通过调用 notifyPropertyChanged(BR.firstName) 可以通知系统 BR.firstName 这个 entry 的数据已经发生变化,需要更新 UI。
Observable 字段
除此之外,还有一种更细粒度的绑定方式,可以具体到成员变量,这种方式无需继承 BaseObservable,一个简单的 POJO 就可以实现。
系统为我们提供了所有的基本类型所对应的 Observable类,例如 ObservableInt、ObservableFloat、ObservableBoolean 等等,还有一个引用类型 所对应的 Observable类ObservableField 。
|
|
就是这样,要访问该值,使用set和get方法:
Observable 集合
Observable集合允许通过键访问这些data对象。ObservableArrayMap的键是引用类型,如String。
在layout文件中,通过String键可以访问map:
同理ObservableArrayList
在layout文件中,通过索引可以访问list:
Binding生成
Binding类的生成链接了layout中variables与Views。如前面所讨论的,Binding的名称和包名可以定制。所生成的Binding类都扩展了android.databinding.ViewDataBinding。
创建
最常见的是在Binding类上使用静态方法.inflate方法载入View的层次结构
如果使用不同的机制载入layout,他可分开绑定:
有时Binding不能提前知道,对于这种情况,可以使用DataBindingUtil类来创建Binding:
带ID的Views
Data Binding 有效降低了代码的冗余性,甚至完全没有必要再去获取一个 View 实例,但是情况不是绝对的,万一我们真的就需要了呢?不用担心,只要给 View 定义一个 ID,Data Binding 就会为我们生成一个对应的 final 变量。
它会生成如下的Binding类:
ViewStubs
ViewStubs跟正常的Views略有不同。他们开始时是不可见的,当他们要么设置为可见或被明确告知要载入时,它们通过载入另外一个layout取代了自己。
由于ViewStub基本上从View的层次结构上消失,在Binding对象的View也必须消失来允许被收集。因为Views是最后的,一个ViewStubProxy对象取带ViewStub,给开发者获得了ViewStub,当它存在以及还可以访问载入的View层次结构时当ViewStub已被载入时。
当载入另一个layout,为新的布局必需创建一个Binding。因此,ViewStubProxy必需监听ViewStub的OnInflateListener监听器并在那个时候建立Binding。因为只有一个可以存在,ViewStubProxy允许开发者在其上设置一个OnInflateListener它会在建立Binding后调用。
Dynamic Variables
以 RecyclerView 为例,Adapter 的 DataBinding 需要动态生成,因此我们可以在 onCreateViewHolder 的时候创建这个 DataBinding,然后在 onBindViewHolder 中获取这个 DataBinding。
注意此处 DataBindingUtil 的用法:
还有另外一种比较简洁的方式,直接在构造 Holder 时把 View 与自动生成的 XXXBinding 进行绑定。
Attribute setters
有了 Data Binding,即使属性没有在 declare-styleable 中定义,我们也可以通过 xml 进行赋值操作。 为了演示这个功能,我自定义了一个 View - NameCard,属性资源 R.styleable.NameCard 中只定义了一个 age 属性,其中 firstName 和 lastName 只有对应的两个 setter 方法。
只要有 setter 方法就可以像下面代码一样赋值:
onClickListener 也是同样道理,只不过我们是在 Activity 中定义了一个 Listener。
转换器 (Converters)
非常重要
使用 Converter 一定要保证它不会影响到其他的属性,例如这个 @BindingConversion- convertColorToString 就会影响到android:visibility, 因为他们都是都符合从 int 到 int 的转换。
在 xml 中为属性赋值时,如果变量的类型与属性不一致,通过 DataBinding 可以进行转换。
例如,下面代码中如果要为属性 android:background 赋值一个 int 型的 color 变量:
只需要定义一个标记了 @BindingConversion 的静态方法即可(方法的定义位置可以随意):
参考博客:https://github.com/LyndonChin/MasteringAndroidDataBinding