DataBinding使用指南(三):生成的binding类

DataBinding使用指南(一):布局和binding表达式

DataBinding使用指南(二):使用可观察的数据对象

DataBinding使用指南(三):生成binding类

DataBinding使用指南(四):BindingAdapter

DataBinding使用指南(五):绑定布局视图到架构组件


版权声明:本文为博主原创文章,欢迎大家转载!

转载请标明出处: http://blog.csdn.net/guiying712/article/details/80352385,本文出自:【张华洋的博客】


DataBinding库会帮我们生成用于访问布局中的变量和View 的Binding类,这一节将说明如何创建和自定义生成的Binding类。

DataBinding库会为每个布局文件生成一个binding类,生成的 binding 类将布局中的 View 与布局变量链接起来,并且我们可以自定义binding 类的名称和包,另外所有生成的 binding 类都继承自ViewDataBinding

默认情况下,该类的名称基于布局文件的名称,将布局名称转换为Pascal格式并向其添加Binding后缀。例如布局文件名是 activity_main.xml,相应的生成MainActivityBinding类 。这个类持有了布局属性(例如user变量)到布局View的所有绑定,并知道如何为绑定表达式分配值。

创建Binding对象


binding 对象应该在 inflat 布局后立即创建,以确保 View 层次在绑定到布局中的表达式视图之前不被修改。将对象绑定到布局的最常见方法是使用绑定类的静态方法,我们可以先将视图层次inflate ,然后使用 binding类的inflate()方法,,膨胀视图层次结构并将其绑定到该层次结构,如下例所示:

@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater());
}

还有另一个版本inflate()方法,它除了LayoutInflater对象之外还需要一个ViewGroup对象,请看下面的例子:

MyLayoutBinding binding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false);

如果使用不同的机制 inflate 布局,则可以分别进行绑定,如下所示:

MyLayoutBinding binding = MyLayoutBinding.bind(viewRoot);

有时候预先不知道绑定类型,在这种情况下,可以使用DataBindingUtil类创建绑定 ,如下面的代码片段所示:

ViewDataBinding binding = DataBindingUtil.inflate(LayoutInflater, layoutId,
    parent, attachToParent);
ViewDataBinding binding = DataBindingUtil.bindTo(viewRoot, layoutId);

如果我们在一个FragmentListViewRecyclerViewAdapter中使用数据绑定 Item,我们可能更偏向于使用绑定类的 inflate()方法 或 DataBindingUtil类,如下面的代码所示:

ListItemBinding binding = ListItemBinding.inflate(layoutInflater, viewGroup, false);
// or
ListItemBinding binding = DataBindingUtil.inflate(layoutInflater, R.layout.list_item, viewGroup, false);

带ID的View


DataBinding库会在binding类中为布局中每个具有ID的View创建一个不可变字段。例如,DataBinding库从以下布局创建TextView类型的firstNamelastName字段:

<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>

DataBinding库一次性从View层次结构中提取包含ID的View,此机制要比调用findViewById()`方法访问View更快。

ID在数据绑定中并不是必须的,但有些情况下仍然需要在代码中访问View。

变量


Databinding库会为布局中声明的每个变量生成访问器方法。例如,下面布局的binding类中会为user,image和note变量生成 setter 和getter方法:

<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>

ViewStub


与普通View不同,ViewStub对象以不可见View开始,当它变得可见时,或被明确告知 inflate 时,他们通过 inflate 另一个布局来替换自身。

由于ViewStub实质上从 View层次结构中消失了,binding对象中的View也必须消失以便垃圾回收。因为这些View是 final 的,所以在生成的绑定类中一个 ViewStubProxy对象会替代ViewStub,让我们可以在ViewStub存在的情况下访问它,并在ViewStub已经 inflate时访问 inflated 的 View 层次结构。

当 inflating另一个布局时,必须为新布局建立绑定,因此,ViewStubProxy必须要监听ViewStubOnInflateListener并在必要时建立绑定。由于在给定时间只有一个监听器可以存在,所以 ViewStubProxy允许我们设置一个OnInflateListener,它在建立绑定后调用。

立即Binding


当一个变量或可观察对象发生更改时,绑定会安排在下一帧更改之前。然而,有时候,绑定必须立即执行,要想强制执行,请使用 executePendingBindings() 方法。

高级Binding


动态变量

有时候,特定的绑定类是未知的。例如,RecyclerView.Adapter针对任意布局进行操作,所以不知道特定的binding类,但它仍然必须在调用onBindViewHolder()方法期间分配 binding 值。

在下面示例中,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();
}

注意:DataBinding库会在模块包中生成一个名为BR的类,其中包含用于数据绑定的资源的ID。在上面的例子中,DataBinding库自动生成了BR.item变量。

后台线程


我们可以在后台线程中更改数据模型,只要它不是集合。 DataBinding在计算期间会本地化每个变量或字段以避免任何并发问题。

自定义binding类名


在默认情况下,绑定类根据布局文件的名称生成,以大写字母开头,删除下划线(_),大写接下来的字母,并加上后缀 Binding。该类放在 databinding模块包下的包中。例如,布局文件 contact_item.xml 生成ContactItemBinding类。如果布局所在模块包是com.example.my.app,则binding类会被放置在 com.example.my.app.databinding包中。

我们可以通过调整data元素的class属性,将 binding 类进行重命名或放置在不同的包中。例如,以下布局会生成ContactItem binding类,位于当前模块的databinding包中:

<data class="ContactItem">
    …
</data>

我们可以通过在类名前添加一个句点来在不同的包中生成binding类。以下示例在模块包中生成binding类:

<data class=".ContactItem">
    …
</data>

我们也可以在要生成binding类的位置使用完整的包名称。以下示例在com.example包中创建ContactItem 绑定类 :

<data class="com.example.ContactItem">
    …
</data>

本文最近更新日期: 2018年4月26日。

DataBinding使用指南(一):布局和binding表达式

DataBinding使用指南(二):使用可观察的数据对象

DataBinding使用指南(三):生成binding类

DataBinding使用指南(四):BindingAdapter

DataBinding使用指南(五):绑定布局视图到架构组件

猜你喜欢

转载自blog.csdn.net/guiying712/article/details/80352385