美文网首页
Android View Binding (视图绑定)

Android View Binding (视图绑定)

作者: panshouren | 来源:发表于2020-05-18 20:00 被阅读0次

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
}

优点

主要的优点就是能少写几行代码 :-)

相关文章

网友评论

      本文标题:Android View Binding (视图绑定)

      本文链接:https://www.haomeiwen.com/subject/vancohtx.html