Google 官方文档
Google 官方文档 CN
Github ViewBindingSample
Android Studio 版本:Android Studio 3.6 Canary 11 及更高版本
在一个 module 中启用 view binding 后,Android Studio 会为该 module 中的每个 xml 布局文件各生成一个类(名为binding class),binding class 包含它所对应的 layout 中的所有 view。
配置 build.gradle
在 module 的 build.gradle 中配置下面代码即可为该 module 启用 view binding。
android {
...
viewBinding {
enabled = true
}
}
要让 view binding 忽略某个 layout,需要在该 layout 文件中添加 tools:viewBindingIgnore="true" 属性。
<LinearLayout
...
tools:viewBindingIgnore="true" >
...
</LinearLayout>
使用方法
binding class (binding 类)的类名根据 layout 文件名以驼峰法生成,并在最后添加 "Binding"; 例如,一个名为 result_profile.xml 的布局文件,生成的 binding 类的名称就是 ResultProfileBinding。
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.java :
文件位置在 (app/build/generated/data_binding_base_class_source_out/debug/out/com/example/viewbindingdemo/databinding/ActivityMainBinding.java)
public final class ActivityMainBinding implements ViewBinding {
@NonNull
private final LinearLayout rootView;
@NonNull
public final Button button;
@NonNull
public final TextView name;
private ActivityMainBinding(@NonNull LinearLayout rootView, @NonNull Button button,
@NonNull TextView name) {
this.rootView = rootView;
this.button = button;
this.name = name;
}
@Override
@NonNull
public LinearLayout getRoot() {
return rootView;
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
return inflate(inflater, null, false);
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
@Nullable ViewGroup parent, boolean attachToParent) {
View root = inflater.inflate(R.layout.activity_main, parent, false);
if (attachToParent) {
parent.addView(root);
}
return bind(root);
}
@NonNull
public static ActivityMainBinding bind(@NonNull View rootView) {
// The body of this method is generated in a way you would not otherwise write.
// This is done to optimize the compiled bytecode for size and performance.
String missingId;
missingId: {
Button button = rootView.findViewById(R.id.button);
if (button == null) {
missingId = "button";
break missingId;
}
TextView name = rootView.findViewById(R.id.name);
if (name == null) {
missingId = "name";
break missingId;
}
return new ActivityMainBinding((LinearLayout) rootView, button, name);
}
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
}
}
在Activity 中使用 view binding
大概看一下生成的 binding 类源码就知道如何使用 view binding 了。
通过静态方法 inflate() 返回 ResultProfileBinding 实例对象,然后使用该对象获取 layout 中各个 view 的对象。getRoot() 方法用来获取 layout 文件的根 view。
ResultProfileBinding 中的各个 view 对象的名字是根据 xml 中对应 view 的 id 生成的,没有配置 id 的 view 不会在 binding 类里面创建对象。
private lateinit var binding: ResultProfileBinding
override fun onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
binding = ResultProfileBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }
}
在 fragments 中使用 view binding
在 onCreateView 中调用 binding 类 inflate 方法。
private var _binding: ResultProfileBinding? = 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 = ResultProfileBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
优点
主要的优点就是能少写几行代码 :-)












网友评论