Android DataBinding源码分析:系统不认识layout标签如何绘制?底层实现;双向绑定是如何执行的?

118 阅读2分钟

一、Data Binding 是什么?​

​Data Binding(数据绑定)​​ 是 Android 官方提供的一种库,用于将 UI 控件(如 TextView、ImageView)与数据源(如 Java/Kotlin 对象、LiveData)​​自动绑定​​。它通过声明式语法,直接在 XML 布局文件中定义数据与视图的关系,无需手动编写更新 UI 的代码,可以实现双向绑定。


二、为什么需要 Data Binding?​

在传统 Android 开发中,开发者面临以下问题:

  1. ​手动同步数据与 UI​

    • 每次数据变化时,需手动调用 findViewById 获取控件,再通过 setText()setImage() 等方法更新 UI,代码冗余且易错。

    • ​示例痛点​​: // 传统方式更新UI user.name = "张三" textView.text = user.name // 手动同步


​三、Data Binding 的核心解决方案​

Data Binding 通过以下机制解决上述问题:

dataBinding {
    enabled true
}
1. ​​声明式 XML 绑定​

直接在布局文件中绑定数据,避免手动操作 UI:

<layout>
    <data>
        <variable name="user" type="com.example.User" />
    </data>
    <TextView
        android:text="@{user.name}" /> <!-- 自动绑定数据 -->
</layout>
2. ​​自动更新 UI​

当数据变化时,UI ​​自动刷新​​(需配合 Observable 对象或 LiveData):

class User : BaseObservable() {
    @Bindable
    var name: String = ""
        set(value) {
            field = value
            notifyPropertyChanged(BR.name) // 通知UI更新
        }
}

// 修改数据后,TextView 自动显示新值
user.name = "李四"
3. ​​支持复杂逻辑​

在 XML 中直接编写表达式(如条件判断、方法调用):

<TextView
    android:text="@{user.age > 18 ? '成年人' : '未成年人'}"
    android:visibility="@{user.hasOrder ? View.VISIBLE : View.GONE}" />
4. ​​双向绑定​

数据与 UI 可以​​双向同步​​(如输入框内容修改后自动更新数据模型):

<EditText
    android:text="@={user.name}" /> <!-- @= 表示双向绑定 -->

三、源码分析

接下来,我们从DataBindingutil类的setcontentview开始看。

viewDataBindin = DataBindingUtil.setContentView(this, R.layout.xxx);

public static <T extends ViewDataBinding> T setContentView(@NonNull Activity activity,
        int layoutId, @Nullable DataBindingComponent bindingComponent) {
    activity.setContentView(layoutId);
    View decorView = activity.getWindow().getDecorView();
    ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content);
    return bindToAddedViews(bindingComponent, contentView, 0, layoutId);
}

可以看到,里面立马就加载了我们的布局,然后添加到根布局里面,我们接着往下看。

图片.png 会生成一个ViewDataBinding对象,

图片.png

布局文件的里面的控件,就都会存放到我们的这个数组里面

图片.png

这也是一个耗内存的地方。

我们还知道,双向绑定,那么必定会有监听布局改变,或者数据改变的地方。

对象创建以后,这里我们就会创建一个监听器出来监听。然后进行数据的绑定和ui的刷新

图片.png

当有数据以后,我们就开始执行runnable的run方法

图片.png

图片.png

跳到这个方法,进行数据绑定和ui刷新。其实还是findViewById,然后使用settext等方法进行文本输入。只不过这些他们帮助我们完成了,如果不写绑定“@=或@”,那么就入下面一样,没有什么set。只不过是完成了findViewById

图片.png

3.2 布局文件会被拆分成两个

  1. layout标签或data

图片.png

  1. 可以绘制的

图片.png

为什么要拆分呢?因为android绘制不认识这个layout标签,因为他既不是自定义的,没有全类名,也不是系统的,所以不认识。需要拆分出来进行绘制。