几天前,谷歌发布了Android Studio 3.6 Canary 11,其主要创新之处在于View Binding,它于5月在Google I / O 2019上进行了描述。

视图绑定是一种工具,可以使编写代码与视图交互的过程变得更加容易。 在特定模块中启用“视图绑定”时,它将为模块中的每个布局文件生成绑定类。 生成的绑定类对象包含指向标记文件的所有视图的链接,该标记文件指定了android:id
。
如何启用
要在模块中启用视图绑定,您需要向build.gradle
文件中添加一个元素:
android { ... viewBinding { enabled = true } }
您还可以指定不需要为特定的标记文件生成绑定类。 为此,您需要在所需标记文件的根视图中指定tools:viewBindingIgnore="true"
属性tools:viewBindingIgnore="true"
。
使用方法
每个生成的绑定类都包含指向标记的根视图( root
)的链接以及指向具有id的所有视图的链接。 生成的类的名称形成为“标记文件名”,翻译为驼峰大小写+“绑定”。
例如,对于标记文件result_profile.xml
:
<LinearLayout ... > <TextView android:id="@+id/name" /> <ImageView android:cropToPadding="true" /> <Button android:id="@+id/button" android:background="@drawable/rounded_button" /> </LinearLayout>
将生成ResultProfileBinding
类,其中包含2个字段: TextView name
和Button button
。 对于ImageView
将不会生成任何内容,因为它没有id
。 同样在ResultProfileBinding
类中ResultProfileBinding
将有一个getRoot()
方法返回根LinearLayout
。
要创建ResultProfileBinding
类的对象,您需要调用静态方法ResultProfileBinding
inflate()
。 之后,您可以将根视图用作“ Activity
的content view
:
private lateinit var binding: ResultProfileBinding @Override fun onCreate(savedInstanceState: Bundle) { super.onCreate(savedInstanceState) binding = ResultProfileBinding.inflate(layoutInflater) setContentView(binding.root) }
以后的binding
可用于获取视图:
binding.name.text = viewModel.name binding.button.setOnClickListener { viewModel.userClicked() }
与其他方法的差异
视图绑定的主要优点是Null安全和Type安全。
同时,如果某个视图在一个布局布局中可用,但在另一layout-land
(例如layout-land
)中@Nullable
用,则将在绑定类中为其生成@Nullable
字段。
另外,如果在不同的标记配置中有一个具有相同ID但类型不同的视图,则将为其生成一个类型为android.view.View
的字段。
(至少在Canary 11的3.6版中)
通常,如果生成的字段具有最可能的特定类型,将很方便。 例如,对于一种配置中的Button
和另一种配置中的TextView
,将生成类型为TextView
的字段( public class Button extends TextView
)。
使用View Binding时,将在编译阶段检测到标记和代码之间的所有不一致,这将避免在应用程序操作期间出现不必要的错误。
在RecyclerView.ViewHolder
用法
为RecyclerView.ViewHolder
创建view
时,没有什么可以阻止使用视图绑定的:
class PersonViewHolder(private val itemPersonBinding: ItemPersonBinding) : RecyclerView.ViewHolder(itemPersonBinding.root) { fun bind(person: Person) { itemPersonBinding.name.text = person.name } }
但是,要创建这样的ViewHolder
将不得不编写一些样板:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PersonViewHolder { val layoutInflater = LayoutInflater.from(parent.context) val itemPersonBinding = ItemPersonBinding.inflate(layoutInflater, parent, false) return PersonViewHolder(itemPersonBinding) }
如果在使用RecyclerView.ViewHolder
时RecyclerView.ViewHolder
inflate(...)
方法不具有layoutInflater
参数,但将从传递的parent
接收它,则将更加方便。
在这里还值得一提的是,在使用视图绑定时,仅在inflate()
方法时通过findViewById()
搜索view
一次。 这提供了优于kotlin-android-extensions
的优势,在默认情况下, view
缓存仅在Activity
和Fragment
起作用,而RecyclerView.ViewHolder
需要其他配置 。
通常,视图绑定是非常方便的事情,很容易在现有项目中开始使用。 创建者黄油刀已经建议切换到视图绑定。
遗憾的是,这种工具几年前没有出现。