Android Architecture Component DataBinding -- 生成的绑定类(翻译)
Android Architecture Component DataBinding – 生成的绑定类(翻译)
原文:https://developer.android.com/topic/libraries/data-binding/generated-binding
Data Binding 库生成绑定类来用于访问 layout 的 variable 和 views。本文展示了如何创建和自定义生成的绑定类。
生成的绑定类链接 layout 中的 variables 和 views。绑定类的名字和包名都是可以自定义的。所有生成的绑定类都继承自 ViewDataBinding
类。
每个 layout 文件都会生成一个 binding class。默认情况下,类名基于 layout 文件的名字。将其转换为 Pascal 大小写, 并向其添加 Binding 后缀。上面的 layout 名字是 activity_main.xml
所以相应生成的类是 ActivityMainBinding
。这个类会持有从 layout 属性(比如,user
变量)到 layout 的 views 的所有绑定,并知道如何为绑定表达式赋值。
创建一个 binding 对象
Binding 对象在 inflating layout 之后马上创建来确保 layout 中 view 层级在使用表达式绑定到 views 之前没有被修改。最常用绑定对象到 layout 的方式是使用绑定类的静态方法。你可以使用绑定类的 inflate()
方法来 inflate view 层级和绑定对象到它自身。如下例子:
1 | override fun onCreate(savedInstanceState: Bundle?) { |
有一个 inflate()
方法的替代版本,它除了 LayoutInflater
对象之外还需要一个 ViewGroup
对象,如下:
1 | val binding: MyLayoutBinding = MyLayoutBinding.inflate(getLayoutInflater(), viewGroup, false) |
如果 layout 是使用不同的机制 inflate 的,它可以单独去绑定,如下:
1 | val binding: MyLayoutBinding = MyLayoutBinding.bind(viewRoot) |
有时无法事先知道绑定类型。在这个情况下,binding 可以使用 DataBindingUtil
类来创建,如下代码片段:
1 | val rootView = LayoutInflater.from(this).inflate(layoutId, parent, attachToParent) |
如果你在 Fragment
,ListView
,RecyclerView
adapter 中使用 data binding,你可能更喜欢使用 bindings classes 的 inflate
) 方法,或者 DataBindingUtil
类,如下所示:
1 | val listItemBinding = ListItemBinding.inflate(layoutInflater, viewGroup, false) |
具有 ID 的 Views
Data Binding 库在绑定类中为每个 layout 中带有 ID 的 view 创建了一个不可改变的属性。比如,下面的 layout 中,Data Binding 库创建了 firstName
和 lastName
两个 TextView
了行的属性:
1 | <layout xmlns:android="http://schemas.android.com/apk/res/android"> |
库一次从 view 层级中取出包括 IDs 的 views。对于 layout 中的每个 view 来说,这个机制会比调用 findViewById()
) 方法更快。
如果它们没有 data binding 则不必要,但是在一些情况下,仍然需要从代码中访问 view。
Variables
Data Binding 库针对每个在 layout 声明了的 variable 生成访问方法。比如,下面的 layout 在绑定类中为 user
,image
和 note
生成 setter 和 getter 方法:
1 | <data> |
ViewStubs
不像普通的 View,ViewStub
对象以不可见的 view 作为开始。当它们被设置可见或者明确地 inflate 时,它们通过 inflating 另一个 layout 来替换它们自己。
因为 ViewStub
本质上在 view 层级上是不可见的,binding 对象中的 view 也必须消失来运行 gc 回收。因为 view 是 final 的,一个 ViewStubProxy
对象在生成的绑定类中取代 ViewStub
,使你可以在 ViewStub
存在时访问它,并在 ViewStub
被 inflate 时访问 view 层次结构。
当 inflate 另一个 layout,必须为新 layout 建立绑定。因此,ViewStubProxy
必须监听 ViewStub
的 OnInflateListener
,并在需要时建立绑定。因为只有一个监听器可以在给定的时间里存在,ViewStubProxy
允许你去设置一个 OnInflateListener
,它会在建立绑定后回调。
立即绑定
当一个 variable 或者 observable 对象改变时,binding 会在下一帧之前调度变化。但是有时 binding 需要立即执行。要强制执行,使用 executePendingBindings()
) 方法。
高级绑定
动态变量
有时,是不知道特定的绑定类的。比如,一个针对任意布局的 RecyclerView.Adapter
是不知道具体特定的绑定类的。在调用 onBindViewHolder()) 方式时,它仍必须要分配 binding 的值。
在下面的例子中,所有 RecyclerView
绑定的布局都有一个 item
变量。BindingHolder
对象有一个 getBinding()
方法返回 ViewDataBinding
基类。
1 | override fun onBindViewHolder(holder: BindingHolder, position: Int) { |
Data Binding 库在 module 包下生成了一个名为 BR 的类,它包含了用户数据绑定的 resources IDs。在上面的例子中,库自动生成了 BR.item 变量。
后台线程
只要数据模型不是集合,你可以在后台线程中更改数据模型。Data Binding 在计算时期对每个variable / field 进行本地化,以避免任何并发问题。
自定义绑定类名
默认情况下,一个绑定名字是基于 layout 的名字生成的,以大写字母开头,移除下划线(_
),大写下一个字母,添加后缀单词 Binding。这个类被放置在这个 module 包下的 databinding
包中。比如,layout 文件 contact_item.xml
生成 ContactItemBinding
类。如果 module 包是 com.example.my.app
,则绑定类则放置在 com.example.my.app.databinding
包中。
通过调整 data
标签的 class
属性,绑定类可以重命名或放置在不同的包中。举例,下面的 layout 在当前的 module 的 databinding
包中 生成 ContactItem
类:
1 | <data class="ContactItem"> |
你可以通过在类名之前加上句点的方式在不同的包中生成绑定类。下面的例子在 module 包中生成绑定类:
1 | <data class=".ContactItem"> |
你也可以是用全包名来指定生成绑定类的名字。下面例子在 com.example
包中创建 ContactItem
绑定类:
1 | <data class="com.example.ContactItem"> |
本文链接:https://blog.wangjiegulu.com/2018/04/15/android_architecture_components_generated_binding/
版权声明:本博客所有文章除特别声明外,均采用 CC BY 4.0 CN协议 许可协议。转载请注明出处。