思路:Binding文件的inflate方法 -> Binding文件的bind方法 -> 生成Bidning文件实例
)
一、实现原理
当某个module打开ViewBinding的功能后,gradle编译的时候回去扫描layout文件,并生成相对应的Binding文件,该文件实现ViewBinding接口。
ViewBinding.java 是一个接口,内部只定义了一个返回View的getRoot()方法
public interface ViewBinding {
* Returns the outermost {@link View} in the associated layout file. If this binding is for a
* {@code <merge>} layout, this will return the first view inside of the merge tag.
@NonNull
View getRoot();
}
生成的binding文件内容
public final class ActivityMainBinding implements ViewBinding {
@NonNull
private final ConstraintLayout rootView;
@NonNull
public final TextView textViewActivity;
private ActivityMainBinding(@NonNull ConstraintLayout rootView,
@NonNull TextView textViewActivity) {
this.rootView = rootView;
this.textViewActivity = textViewActivity;
}
@Override
@NonNull
public ConstraintLayout 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.
int id;
missingId: {
id = R.id.textViewActivity;
TextView textViewActivity = rootView.findViewById(id);
if (textViewActivity == null) {
break missingId;
}
return new ActivityMainBinding((ConstraintLayout) rootView, textViewActivity);
}
String missingId = rootView.getResources().getResourceName(id);
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
}
}
二、使用流程解析
1.使用binding文件的inflate方法,该方法内部通过LayoutInflater,将layout布局文件转化为View。最终调用bind方法
@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);
}
2.bind方法内部通过findViewById 去绑定元素,最终调用构造方法给每个view赋值并且生成binding文件
@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.
int id;
missingId: {
id = R.id.textViewActivity;
TextView textViewActivity = rootView.findViewById(id);
if (textViewActivity == null) {
break missingId;
}
return new ActivityMainBinding((ConstraintLayout) rootView, textViewActivity);
}
String missingId = rootView.getResources().getResourceName(id);
throw new NullPointerException("Missing required view with ID: ".concat(missingId));
}
三、优点
1.null 安全,会创建对View的直接引用,因此不存在因View ID 无效而引发 Null 指针异常的风险
2.类型转换安全,每个绑定类中的字段均具有与它们在 XML 文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。