美文网首页Android
Android中的DataBinding的原理浅析

Android中的DataBinding的原理浅析

作者: TianFB | 来源:发表于2019-07-17 11:47 被阅读0次

    一、什么是DataBinding

    知道DataBinding的应该也会知道MVVM设计模式,该模式实现了View与Model的双向绑定从而实现了View和Model的同步更新。MVVM是一种架构思想而DataBinding就是实现这一思想的工具。

    二、DataBinding的使用

    我们要对DataBinding进行原理分析前,首先要会使用DataBinding。
    在build.gradel中配置DataBinding

    android {
        ...
        dataBinding{
            enabled true
        }
    }
    

    对View的布局文件进行配置,使用layout作为跟布局标签。使用data标签进行DataBinding的绑定。控件中可以使用@{}进行绑定,@{}为单向绑定@={}为双向绑定

    <?xml version="1.0" encoding="utf-8"?>
    <layout xmlns:android="http://schemas.android.com/apk/res/android">
        <!--DataBinding的配置文件-->
        <data>
            <!--name属性相当于声明了一个全局属性、type指定name对应的具体的数据类或是MVVM中VM-->
            <variable
                    name="userInfo"
                    type="com.scjd.framemodel_databinding.UserInfo"/>
        </data>
        <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent"
                      android:padding="50dp"
                      android:orientation="vertical">
            <EditText android:layout_width="match_parent" android:layout_height="wrap_content"
                      android:text="@={userInfo.userName}"/>
            <EditText android:layout_width="match_parent" android:layout_height="wrap_content"
                      android:text="@{userInfo.passWord}"/>
            <View android:layout_width="wrap_content" android:layout_height="wrap_content"/>
        </LinearLayout>
    </layout>
    

    声明一个数据类,使用PbservableField声明属性并通过范型指定数据类型。

    public class UserInfo {
        public ObservableField<String> userName = new ObservableField<>();
        public ObservableField<String> passWord = new ObservableField<>();
    }
    

    在Activity中进行绑定

    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
    
            var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)
            var userInfo = UserInfo()
            userInfo.userName.set("xixi")
            userInfo.passWord.set("123")
            binding.userInfo = userInfo
        }
    }
    

    以上就是一个通过DataBinding实现双向绑定的例子。

    三、Data Binding的原理分析

    我们通过上面的例子对DataBinding进行原理分析。首先我们要知道DataBinding使用了apt技术,我们build项目时DataBinding会生成多个文件,我们可以在build文件中查看

    图片.png 图片.png

    DataBinding还将原有的activity_main.xml文件进行了拆分,分别是activity_mian.xml和activity_main-layout.xml。

    activity_main.xml

    通过上面的代码我们发现DataBinding将原有的layout和data标签去除了。并为根布局声明了一个layout/文件名_0的tag,为其他使用到@{}或@={}的控件按顺序添加了一个binding_X的tag。

    activity_main-layout.xml

    该配置文件中详细的记述了<Variables declared="true" type="com.scjd.framemodel_databinding.UserInfo" name="userInfo"> 我们声明的全局变量,变量指向的数据类型的绝对路径。<Target tag="binding_1" view="EditText">tag对应的View类型。<Expression text="userInfo.userName" attribute="android:text">控件绑定具体属性和Model中的具体属性。<TwoWay>true</TwoWay>是否是双向的。

    接下来我们通过Activity中的 var binding: ActivityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main)进行入手

    方法中通过activity的setContentView加载布局,并通过window找到id为content的ViewGroup,它是一个FrameLayout用于加载我们添加的布局文件。接下来就是bindToAddedViews方法。

    parent中的子View就是我们布局文件中的根布局LinearLayout,所以走的是if中的代码

    bind方法又调用了DataBinderMapperImpl中的getDataBinder方法。

    通过一系列的条件判断之后返回了一个ActivityMainBindingImpl对象,接下来我们看它的构造方法。

    上面的代码看着非常的多,但是它就是将布局中的含有databinding赋值的tag控件一一存入bindings的Object的数组中并返回。

    该方法中将获取的View数组赋值给成员变量,接下来看invalidateAll()方法。

    上面代码调用过来就是为了执行mRebindRunnable。在看该Runnable中的executePendingBindings()方法

    上面也是对一些状态进行了判断添加一下回调,主要的还是executeBindings()方法。

    看了上面的方法是不是有一种终于熬到头的感觉了呢,当((dirtyFlags & 0xeL) != 0)或((dirtyFlags & 0xdL) != 0)成立时就会把Model中的数据set到相应的View中,这个就是单向的M->V。((dirtyFlags & 0x8L) != 0)成立时就是V->M它为双向绑定的控件添加了一个内容变化的监听mboundView1androidTextAttrChanged

    当控件中的内容发生变化时,就会更新到Model上。

    activity中为userInfo赋的值就是上面的mUserInfo。
    通过上面的代码我们对DataBinding的绑定过程又了一定的了解,但是还有两个问题我们没有解决,那就是View和Model的变化有时在哪里监听的呢。

    还记得上面的mRebindRunnable吗?通过对它的查找我们在ViewDataBinding的静态代码块中发现了端倪。

    看到上面的代码是不是一下就明白了V的变化监听了呢。

    DataBinding通过布局中的tag将控件查找出来,然后根据生成的配置文件将V与M进行对应的同步操作,设置一个全局的布局变化监听来实时更新,M通过他的set方法进行同步。

    该文档是自己的学习记录如有错误欢迎指出。

    相关文章

      网友评论

        本文标题:Android中的DataBinding的原理浅析

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