ViewBinding中文官网
ViewBinding 的出现就是为了替代 findViewById 的。以前我们写完布局后就要在代码中使用 findViewById 方法找到 xml 文件中对应的 view ,这样耗时费力,还有可能会出错,比如 view 跟 id 不一致等等,奇奇怪怪的问题,毕竟人力和时间有限,这种简单繁杂的工作直接交给 IDE 去做不是更好,它们做的检测工作肯定比人来更精准。
Android Studio 3.6 Canary 11 之后的版本都支持使用ViewBinding这个功能模块了,只需要在 app/build.gradle 文件添加如下代码即可:
android {
...
viewBinding {
enabled = true
}
}
Android Studio 4.0 后改成了这样:
android {
...
buildFeatures {
viewBinding = true
}
}
通过上面的配置后,我们工程目录下的 xml 布局文件,就会生成对应的 Binding 类。例如:activity_main.xml 就会生成 ActivityMainBinding 类。这个类就会完成 findViewById 的工作。
当然,如果我们不想我们的 xml 文件生成 Binding 类,我们可以在 xml 布局文件中根 view 写入
tools:viewBindingIgnore="true"
Binding 类生成的路径在build/generated/data_binding_base_class_source_out/debug/out/com/xxx/yyy/databinding/
目录下。
我们来看下 ViewBinding 帮我们生成的类的代码结构是怎么样的。
public final class ActivityMainBinding implements ViewBinding {
@NonNull
private final ConstraintLayout rootView;
@NonNull
public final TextView idText;
private ActivityMainBinding(@NonNull ConstraintLayout rootView, @NonNull TextView idText) {
this.rootView = rootView;
this.idText = idText;
}
@NonNull
public ConstraintLayout getRoot() {
return this.rootView;
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
return inflate(inflater, (ViewGroup)null, false);
}
@NonNull
public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater, @Nullable ViewGroup parent, boolean attachToParent) {
View root = inflater.inflate(2131361820, parent, false);
if (attachToParent) {
parent.addView(root);
}
return bind(root);
}
@NonNull
public static ActivityMainBinding bind(@NonNull View rootView) {
int id = 2131165279;
TextView idText = (TextView)rootView.findViewById(id);
if (idText == null) {
String missingId = rootView.getResources().getResourceName(id);
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
} else {
return new ActivityMainBinding((ConstraintLayout)rootView, idText);
}
}
}
Android Studio 主要帮我们实现了3个方法,getRoot, inflate, bind 。最重要的就是 bind 方法了。这个方法才是真正实现 findViewById 的地方。
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
binding.idText.setText("ViewBinding");
}
inflate 方法
ActivityMainBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
binding = FragmentMainBinding.inflate(inflater, container, false);
binding.idText.setText("Fragment");
return binding.getRoot();
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
或者 bind 方法
FragmentMainBinding binding;
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
binding = FragmentMainBinding.bind(view);
binding.idText.setText("Fragment");
}
@Override
public void onDestroyView() {
super.onDestroyView();
binding = null;
}
通过注解实现 findViewById。
通过 Kotlin 语言特性底层实现 findViewById。
通过 annotation processor 实现,会影响工程的构建速度。
Null 安全
类型安全
ViewBinding 总的来说就是替换 findViewById 的。可以节省我们的开发时间,提高效率。从以前的人工查找绑定,改为 Android Studio 帮助我们查找绑定并生成对应的类。从而帮助开发人员从繁琐的 view 查找绑定中抽身出来,做更有意义的事情。