Android ViewBinding:源码如何看,底层是如何的?

174 阅读2分钟

一、viewBinding 是什么?

​ViewBinding​​ 是 Android 官方提供的一个轻量级视图绑定工具,​​核心功能是替代 findViewById​,通过自动生成绑定类(如 ActivityMainBinding)直接访问布局中的视图控件。


二、为什么有databinding,还设计了viewbinding呢?

  • DataBinding​​:
    ​强在数据绑定​​,适合需要将数据直接映射到 UI 的场景(如实时更新用户信息),但代价是编译时间和复杂度。
  • ​ViewBinding​​:
    ​强在简单高效​​,适合纯 UI 绑定,无数据逻辑的场景。作为官方替代 findViewById 的方案,是大多数项目的首选。

两者定位不同,根据需求灵活选择。


三、viewBinding的使用

3.1. 启用View Binding

在模块的 build.gradle 文件中启用:

android {
    buildFeatures {
        viewBinding true
    }
}

当你启用 View Binding 后,Gradle 插件会在编译时扫描项目中所有的 XML 布局文件。比如你有一个 activity_main.xml,编译器会发现它,并准备生成对应的代码。

3.2. 在Activity中使用

  • ​初始化绑定对象​​:通过生成的绑定类(如 ActivityMainBinding)访问视图。
  • ​设置布局​​:使用 binding.root 作为根视图。
class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        // 访问视图
        binding.textView.text = "Hello, View Binding!"
    }
}
// 伪代码示意
public class ActivityMainBinding {
  // 布局根视图(比如 ConstraintLayout)
  public final ConstraintLayout root; 

  // 布局中带 ID 的视图
  public TextView textView;  // 对应 XML 中 android:id="@+id/textView"
  public Button button;      // 对应 XML 中 android:id="@+id/button"
  // ...其他视图

  // 通过 inflate 方法加载布局并绑定视图
  public static ActivityMainBinding inflate(LayoutInflater inflater) {
    // 1. 加载布局文件,创建视图树
    ConstraintLayout root = inflater.inflate(R.layout.activity_main, null);
    // 2. 自动绑定所有带 ID 的视图
    TextView textView = root.findViewById(R.id.textView);
    // ...绑定其他视图
    return new ActivityMainBinding(root, textView, button, ...);
  }
}

3.3 看看他源码

从ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root)进去。

但你会发现,跳到了xml,看不到源码,我们需要到build里面看看。

图片.png

图片.png

其实最终逻辑都一样,还是要调用inflate分发,将布局转换成对象,然后添加到根布局上。

@NonNull
public static ActivityCoreParametersBinding inflate(@NonNull LayoutInflater inflater,
    @Nullable ViewGroup parent, boolean attachToParent) {
  View root = inflater.inflate(R.layout.activity_core_parameters, parent, false);
  if (attachToParent) {
    parent.addView(root);
  }
  return bind(root);
}

最终还是使用findViewById去拿到对象

图片.png

内存管理注意事项

在 Fragment 中,View Binding 对象可能持有视图的引用。如果 Fragment 生命周期结束但 Binding 对象未释放,可能导致内存泄漏。因此需要手动置空:

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null // 释放引用
}

总结:View Binding 的核心思想

​“用代码生成代替重复劳动”​​。编译器自动帮你写好了所有 findViewById 的代码,并确保类型安全和性能优化。开发者只需关注业务逻辑,不再被繁琐的视图查找困扰。