前言,以下为Kotlin语言环境
在android官方文档中,视图绑定可以用于替代findViewById.并且,当启用视图绑定之后,系统会为项目中的每个XML文件生成一个绑定类.绑定类的实例包含其布局中的所有具有ID的直接引用
一、启用视图绑定
在app下的目录下的build.gradle添加
viewBinding{
enabled = true
}
如果不想某一个布局文件生成绑定类,那么可以在该布局文件的最外层的Layout中设置属性:tools:viewBindingIgnore=“true”
二、使用步骤
1.假设XML布局名称为activity_main.xml
代码如下(示例):
<LinearLayout
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试"
android:textSize="25sp"
/>
<Button
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="测试"
android:textSize="25sp" />
</LinearLayout>
这个XML布局所生成的绑定类的名称就是:ActivityMainBinding
2.对应的kt文件中的代码(Activity),
android官方给予的步骤是:
- 调用生成的绑定类中包含的静态 inflate() 方法。此操作会创建该绑定类的实例以供 Activity 使用。
- 通过调用 getRoot() 方法或使用 Kotlin 属性语法获取对根视图的引用。
- 将根视图传递到 setContentView(),使其成为屏幕上的活动视图
class MainActivity : AppCompatActivity() {
private lateinit var binding:ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//1.创建该绑定类的实例,供予Activity使用
binding = ActivityMainBinding.inflate(layoutInflater)
//2.获取对根视图的引用
/*
* root属性对应getRoot()方法
* 为相应布局文件的根视图的直接引用
* 返回LinearLayout根视图
* */
val view = binding.root
//3.显示出来
setContentView(view)
//测试部分
binding.text2.setOnClickListener {
binding.text1.text = "变换"
}
}
}
从测试部分的代码可以看见,我们无需再去进行复杂的控件绑定和命名,可以直接通过binding对象直接进行引用
3.对应kt文件中的代码(Fragment)
Android官方给的步骤是
- 调用生成的绑定类中包含的静态 inflate() 方法。此操作会创建该绑定类的实例以供 Fragment 使用。
- 通过调用 getRoot() 方法或使用 Kotlin 属性语法获取对根视图的引用。
- 从 onCreateView() 方法返回根视图,使其成为屏幕上的活动视图。
注意:inflate() 方法会要求您传入布局膨胀器。如果布局已膨胀,您可以调用绑定类的静态 bind() 方法。如需了解详情,请查看视图绑定 GitHub 示例中的例子。PS:这一段博主没理解,但以后会深入了解
这里假设Fragment的XML文件名为fragment_one,那么对应的绑定类就是FragmentOneBinding
private var _binding: FragmentOneBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentOneBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
//关于这一步,Android官方给出的解释是,fragment的存在时间比其视图长,所以需要重写这个方法,清楚对绑定类实例的所有引用
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
与findViewById的区别
与使用 findViewById 相比,视图绑定具有一些很显著的优点:
-
Null 安全:由于视图绑定会创建对视图的直接引用,因此不存在因视图 ID 无效而引发 Null指针异常的风险。此外,如果视图仅出现在布局的某些配置中,则绑定类中包含其引用的字段会使用 @Nullable 标记。
-
类型安全:每个绑定类中的字段均具有与它们在 XML 文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。
这些差异意味着布局和代码之间的不兼容将会导致构建在编译时(而非运行时)失败。
博主的想法
我觉得视图绑定是比findViewById好用的,我在实际开发中,总是在对控件命名时,用一大段的进行命名,比如fragment下的tButton提交控件:我命名为fragment_submit,因为主要是在编写kt代码时,比较好寻找,有了视图绑定,就可以直接命名为submit,不需要我再去命名一长串作为区分了