当前位置: 首页>编程语言>正文

ViewBind实现原理

思路: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 文件中引用的视图相匹配的类型。这意味着不存在发生类转换异常的风险。


https://www.xamrdz.com/lan/5m82016312.html

相关文章: