期待已久的Android中的视图绑定

几天前,谷歌发布了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 nameButton button 。 对于ImageView将不会生成任何内容,因为它没有id 。 同样在ResultProfileBinding类中ResultProfileBinding将有一个getRoot()方法返回根LinearLayout


要创建ResultProfileBinding类的对象,您需要调用静态方法ResultProfileBinding inflate() 。 之后,您可以将根视图用作“ Activitycontent 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.ViewHolderRecyclerView.ViewHolder inflate(...)方法不具有layoutInflater参数,但将从传递的parent接收它,则将更加方便。


在这里还值得一提的是,在使用视图绑定时,仅在inflate()方法时通过findViewById()搜索view一次。 这提供了优于kotlin-android-extensions的优势,在默认情况下, view缓存仅在ActivityFragment起作用,而RecyclerView.ViewHolder需要其他配置


通常,视图绑定是非常方便的事情,很容易在现有项目中开始使用。 创建者黄油刀已经建议切换到视图绑定。


遗憾的是,这种工具几年前没有出现。

Source: https://habr.com/ru/post/zh-CN467295/


All Articles