Data Binding 系列(五)生成绑定类

1,302 阅读3分钟

Data Binding 生成的绑定类用来访问布局中的变量和 view 控件。本章讲述了怎么创建和自定义生成的绑定类。

绑定类保存了变量和 view 变量的绑定关系。绑定类的包路径和名字都是可以自定义的。所有生成的绑定类都继承了 ViewDataBinding 类。

每个布局文件都会生成一个对应的绑定类,默认情况下,绑定类的名字取决于布局文件的名字,布局文件的名字转为驼峰写法并添加 Binding 后缀。如 activity_main.xml 布局文件对应的绑定类是 ActivityMainBinding

生成绑定对象

绑定对象应该在加载布局的时候立即实例化,可以使用 inflate 方法,如下所示:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    val binding: MyLayoutBinding = MyLayoutBinding.inflate(layoutInflater)
}

inflate 还有一个重载方法,如下所示:

val binding: MyLayoutBinding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false)

如果布局已经使用其他的方式加载了,可以使用如下方式绑定:

val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot)

有时候,绑定类的类型是不知道的,可以使用 DataBindingUtilbind 方法:

val viewRoot = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent)
val binding: ViewDataBinding? = DataBindingUtil.bind(viewRoot)

View 的 ID

对于布局文件中每个有 id 的控件,都会在绑定类中生成一个对应的字段。如下所示,针对布局文件中的 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>

绑定类一次性保存了每一个有 id 的控件实例,这比 findViewById() 高效得多。

变量

对于布局文件中声明的每一个变量,DataBinding 都在绑定类中生成了对应的 get()set() 方法。如下所示,变量 userimagenote ,在绑定类都有对应的访问方法:

<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

不同于通常的 viewViewStub 是一个不可见的 view,当它调用 inflate 等方法显示的时候,它会被其他布局替代。

ViewStub 在调用 inflate 等方法后会被其他 view 替代,所以需要考虑绑定类中的 ViewStub 实例的回收和新生成 view 的绑定问题。所以在绑定类中并没有生成 ViewStub 实例,而是生成了 ViewStubProxy 实例,当 ViewStub 存在的时候,ViewStubProxy 可以用来访问它;当 ViewStub 被其他 view 替代后,ViewStubProxy 可以用来访问这个新的 view

ViewStubProxy 必须监听 ViewStubOnInflateListener ,当收到通知的时候,建立与新布局的绑定关系。我们可以给 ViewStubProxy 设置一个 OnInflateListener ,当与新布局建立绑定关系后,会通知这个监听器。

立即更新

当数据变化时,view 会在下一帧开始更新,如果我们需要 view 立即更新,可以调用 executePendingBindings() 方法。

自定义绑定类的名字和路径

假如有一个 content_item.xml 的布局文件,默认的绑定类名是 ContentItemBinding ,默认的路径是包名。

如下所示,我们可以自定义绑定类名为 ContentItem,路径为 com.example :

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