本文为菜鸟学习笔记兼翻译练习用,翻译可能会不准确,细节请以原文为准,如有不足之处还请见谅,若能斧正,小弟不胜感激。原文地址:Google Data Binding Library
创建的绑定类(Generated Binding)
创建的绑定类在布局中将变量和控件连接在了一起。和之前讨论的一样,绑定类的名称和package是可以自定义的。所有的创建的绑定类都扩展了ViewDataBinding类。
创建
绑定类必须在布局填充之后立即创建以保证控件的层级优先级不会被带有表达式的控件干扰。绑定到布局的方法有几种。最常见的是在绑定类上使用静态方法。布局填充方法一步完成控件的分层部署并完成绑定。下边是一个简单版的实现:只需要一个LayoutInflater或者再加上一个ViewGroup就可以:
MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater);
MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false);
如果布局使用的是不同的实现方式,它可以单独绑定:
MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
有时绑定不能提前预知, 这种情况下,绑定可以通过DataBindingUtil类创建:
ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
定义了ID的控件
每个在布局里有ID的控件,DataBinding都会为它创建一个public final的属性。DataBinding会对View树进行筛选,挑出有ID的控件。这个机制会比使用findViewById来得要快。例如:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="user" type="com.example.User"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"
android:id="@+id/firstName"/>
<TextView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastName}"
android:id="@+id/lastName"/>
</LinearLayout>
</layout>
上述代码会创建一个包含下边两个属性的绑定类:
public final TextView firstName;
public final TextView lastName;
ID在没有DataBinding的情况下几乎不需要,但是仍然有一些场景需要在代码中访问控件。
变量
每个变量都会有访问器方法:
<data>
<import type="android.graphics.drawable.Drawable"/>
<variable name="user" type="com.example.User"/>
<variable name="image" type="Drawable"/>
<variable name="note" type="String"/>
</data>
上述代码会在绑定类中创建getter和setter:
public abstract com.example.User getUser();
public abstract void setUser(com.example.User user);
public abstract Drawable getImage();
public abstract void setImage(Drawable image);
public abstract String getNote();
public abstract void setNote(String note);
ViewStubs
ViewStub和一般的View不太一样。它们在开始时不可见,当它们被告知要可见或准确的要填充到布局时, 它们会用另一个布局将自己替换。
由于ViewStub实际上会从布局中消失,绑定对象内的View必须也消失以支持采集。因为View是final修饰的,所以一个ViewStubProxy对象替换了ViewStub,使得开发者得以访问ViewStub和当ViewStub在被部署后替换的View层。
当部署了另一个布局时,必须为新的布局创建绑定类。所以,ViewStubProxy必须监听ViewStub.OnInflateListener并且在那时创建绑定。由于只能有一个(绑定?)存在,ViewStubProxy允许开发者设置一个OnInfalteListener,这个监听器会在创建绑定时调用。
高级绑定技巧
动态绑定变量
有时,我们无法了解绑定的细节。比如,RecyclerView.Adapter对任意的布局操作不能知道绑定类的细节。它需要onBindViewHolder(VH, int)方法分配的绑定值。
在下边的例子里,RecyclerView为所有的布局绑定了“item”变量。BindingHolder有一个getBinding方法返回ViewDataBinding基类。
public void onBindViewHolder(BindingHolder holder, int position) {
final T item = mItems.get(position);
holder.getBinding().setVariable(BR.item, item);
holder.getBinding().executePendingBindings();
}
快速绑定
当一个变量或一个观察类变化,绑定类会在下一次变化发生前预定变化。然而有时绑定必须立刻执行。可以用executePendingBindings()方法强制执行。
后台线程
你可以在后台线程更改你的data model,只要它不是一个集合。DataBinding会在估值时将每个变量/属性局部化以避免并发场景。
下一篇从Attribute Setters开始翻译。