viewBinding
Android Studio 3.6+支持;
从 Android Studio 3.6 开始,viewBinding又叫视图绑定,能够通过生成绑定对象来替代 findViewById,从而可以帮您简化代码、移除 bug,并且从 findViewById 的模版代码中解脱出来。
官方推荐使用视图绑定替代 Kotlin 合成方法和 ButterKnife;
特性
- viewBinding是一个轻量的findViewById的替代方案;
- 视图绑定没有添加任何额外的逻辑,他只是把视图属性暴露给您,从而帮您在不使用 findViewById 的情况下也能调用它们。这样一来便保证了生成文件简洁性(当然也避免了拖慢构建速度)。
- 视图绑定完美支持 Java 和 Kotlin 编程语言。
- 视图绑定会为 Module 内所有的布局文件生成绑定对象, 例如:
# eg
activity_awesome.xml → ActivityAwesomeBinding.java
- 布局文件中每一个带有 id 的视图都会在绑定对象中有一个对应的属性,包括include标签,并且会为根布局生成 rootView 属性并通过 getRoot 暴露给开发者,这个生成的视图属性将拥有正确的类型,并且空安全。
API介绍
创建视图绑定对象实例
每个xml布局生成的XxBinding类,都有三个静态方法用来在使用的地方创建绑定对象实例, 三个静态方法如下:
- inflate(inflater):在例如 Activity onCreate 方法里,这类没有父视图需要被传入的场合使用。
- inflate(inflater, parent, attachToParent):在 Fragment 或 RecyclerView Adapter (或者说 ViewHolder 中) ,这类您需要传递父级 ViewGroup 给绑定对象时使用。
- bind(rootView):在您已经获得对应视图,并且只想通过视图绑定来避免使用 findViewById 时使用。这个方法在使用视图绑定改造和重构现有代码时非常有用。
//eg: 在activity中创建
XxBinding binding = XxBinding.inflate(getLayoutInflater());
viewBinding获取子视图对象
直接子视图
对于布局的直接子视图可以通过viewBinding直接获取视图对象;
binding.tvText.setText("");
include布局子视图
视图绑定会为 Module 下的每一个布局文件生成一个绑定对象,这个说法在布局文件被另一个布局文件使用 include 引入时依然适用;
在使用引入布局的时候,视图绑定会创建一个被引入布局绑定对象的引用。引用名跟使用普通视图一样,依然是 include 标签的id,注意 include 标签需要有一个 id 才能在绑定对象中生成对应的属性。
获取通过include引用的布局的内部视图的示例, 布局信息如下:
<!-- activity_awesome.xml -->
<androidx.constraintlayout.widget.ConstraintLayout>
<include android:id="@+id/includes"
layout="@layout/included_buttons"/>
</androidx.constraintlayout.widget.ConstraintLayout>
<!-- included_buttons.xml -->
<androidx.constraintlayout.widget.ConstraintLayout>
<Button android:id="@+id/include_me" />
</androidx.constraintlayout.widget.ConstraintLayout>
视图绑定会在 ActivityAwesomeBinding 中生成一个 IncludedButtonsBinding 的引用,拿到这个引用就可以继续获取include子视图对象。
public final class ActivityAwesomeBinding implements ViewBinding {
@NonNull
public final IncludedButtonsBinding includes;
}
对比dataBinding
不同点
- databinding可以自定义binding的类名,viewbinding不可以。
- databinding可以将view和界面上的数据进行双向绑定,viewbinding不行,视图绑定只是 findViewById 的轻量取代方案;
关联性
- 数据绑定和视图绑定可以生成同样的组件,它们可以同时工作。
- 您可以在同一 Module 中同时使用数据绑定和视图绑定。在两者都被开启时,使用 “layout” 标签的布局会由数据绑定来生成绑定对象;而其余的布局则由视图绑定生成绑定对象
使用实战
开启视图绑定无须引入额外依赖,从 Android Studio 3.6 开始,视图绑定将会内建于 Android Gradle 插件中。需要打开视图绑定的话,只需要在 build.gradle 文件中配置 viewBinding 选项, 配置完成后,视图绑定就会为所有布局文件自动生成对应的绑定类。无须修改原有布局的 XML 文件,视图绑定将根据您现有的布局自动完成所有工作。
1. 开启viewBinding
- Android Studio 3.6.0:
// 需要 Android Gradle Plugin 3.6.0
android {
viewBinding {
enabled = true
}
}
- Android Studio 4.0:
// Android Studio 4.0
android {
buildFeatures {
viewBinding = true
}
}
2. 使用
视图绑定将会根据现有的 XML 文件,为 Module 内所有的布局文件生成绑定对象。您可以在任何需要填充布局的地方使用绑定对象,比如 Fragment、Activity、甚至是 RecyclerView Adapter(或者说是 ViewHolder 中)。
禁止对某布局生成viewBinding对象
只需要在布局的根view添加如下忽略即可:
<FrameLayout
...
tools:viewBindingIgnore="true"/>
在Activity中使用
假如您有一个布局文件名叫 act_text.xml,其中包含了一个TextView文本视图。视图绑定会为这个布局生成一个名叫 ActTextBinding 的类,布局文件中所有拥有 id 的视图,都会在这个类中有一个对应的属性;
- 创建xml布局文件:act_text.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:viewBindingIgnore="false">
<TextView
android:id="@+id/tv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
- activity中引用:
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActTextBinding binding = ActTextBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
//对act_text.xml中id为tv_content的TextView设置内容
binding.tvContent.setText("");
}
- 查看生成的viewBinding对象代码:
//生成的文件位置:app/build/generated/data_binding_base_class_source_out/debug/out/com/x/x/databinding/ActTextBinding.java
public final class ActTextBinding implements ViewBinding {
@NonNull
private final ConstraintLayout rootView; //自动为根view生成一个对象
@NonNull
public final TextView tvContent;
}