生成绑定 自动生成的绑定类将layout中定义的变量和view关联起来.根据前面的讨论,绑定类的名字和所在的包名是可以定制的.共同点是:所有的绑定类都继承于ViewDataBinding.
生成 绑定关系应该在解析完布局之后马上创建,防止后续的代码影响到布局结构.这里有几种方法可以对一个layout建立绑定关系,最常用的是使用绑定类的静态方法.inflate方法可以同时完成view层级解析和绑定关系建立.(译者注:相对于反复findviewbyid,这种一次解析完成映射可以节省不少时间) 下面是两个简单的绑定示例,
1 2 MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater); MyLayoutBinding binding = MyLayoutBinding.inflate(layoutInflater, viewGroup, false );
如果你的view已经inflate出来了.仅仅需要绑定.可以这样做:
1 MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);
有时候你可能想写一些工具类方法,即并不知道需要绑定类的类型,你可以使用DataBindingUtils:
1 2 3 ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId, parent, attachToParent); ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);
组件id 针对layout中指定了id的view组件,会对应生成public final的变量.绑定过程解析一次不举文件,找出带有id的组件.这个比多次findViewById要快很多.例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <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 >
会在绑定类中生成这两个变量
1 2 public final TextView firstName;public final TextView lastName;
不指定id也可以使用databind,但是如果后期需要访问这个view的话,还是需要指定id的.
变量 每个变量都会生成get/set方法.
1 2 3 4 5 6 <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 >
上面的layout会在bind类中生成以下方法
1 2 3 4 5 6 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 ViewStubs和普通view有点不同.它们一开始是不可见的,而且并不会解析到view层级中.只有需要显示的时候,才会替换原有的布局,并显示出自身. 因为ViewStub最终会从view层级中移除,那么绑定类中对应的属性应该也可以及时回收. 但是因为view是final类型的,所以用ViewStubProxy来取代原本的ViewStub,让开发者可以访问这个ViewStub,并且当对应的view显示时,可以访问到那个view. 当解析另外一个布局文件的时候,绑定对象也应该和新的布局关联起来.因此,ViewStubProxy需要监听ViewStub的 OnInflateListener回调接口来建立绑定关系.开发者可以在ViewStubProxy上设置一个OnInflateListener ,当绑定建立的时候,开发者可以收到回调函数.(译者注:ViewStub用得实在不多,此处没有试验)
绑定进阶 动态数据模型 有时候,并不能知道具体绑定的数据模型.比如在使用RecyclerView.Adapter这样的适配器时,只有在onBindViewHolder中才能知道对应的数据模型. 这种情况下,假设adapter的layout中都有一个item变量.这样你可以使用setVarible方法来将数据模型和item绑定在一起.
1 2 3 4 5 public void onBindViewHolder (BindingHolder holder, int position) { final T item = mItems.get(position); holder.getBinding().setVariable(BR.item, item); holder.getBinding().executePendingBindings(); }
立即刷新 当数据模型变化时,绑定关系会在下一个周期中刷新页面,这可能会有一点延迟.如果想要强制刷新,可以使用executePendingBindings)方法.
后台线程 只要数据模型不是一个集合,你就可以在任意子线程中进行修改.databind会通过保存到本地来帮你解决同步问题.