dataBinding源码分析

95 篇文章 0 订阅

上篇写了dataBinding的使用和封装,今天我们就分析下源码。

首先我们从 DataBindingUtil.setContentView(this,R.layout.activity_main);方法作为入口,发现最后还是调用activity的setContentView()方法。

//最后会调用bind()方法,这个方法会调用 DataBindingMapper类的getDataBinder()方法

点击DataBindingMapper类发现getDataBinder方法是个抽象方法,他的子类DataBindingMapperImpl类实现了这个方法,我们看看这个方法根据view的tag创建一个ActivityMainBindingImpl类(命名是根据xml布局名+BindingImpl)

 

这时有人会问,哪个tag怎么来的,其实,当我们再布局里面使用layout作为根布局再写了data标签,build后,系统会自动生成两个xml文件

 

//我们点开activity_main 发现里面的布局就是去掉layout和data的正常布局,并且在每个控件添加了一个tag标记

 

//再打开activity_mian_layout文件,发现就是记录所有节点标签的信息,比如名称代码的开始行结束行等等信息。(如果你开代码是一行的,可以格式化代码 Windows快捷键 ctrl + shift+ F)

 

回到我们上面讲的DataBinderMapperImpl的getDataBinder()方法,根据布局tag创建对应的**BindingImpl类;其实ActivityMainBindingImpl类是ActivityMainDataBining的子类 ;ActivityMainDataBining是ViewDataBinding的子类;其实DataBinding.setContentView()方法设置布局,根据布局tag返回对应的ViewDataBinding对象;DataBinding.setContextView()源码就分析到这了。

 

------------------------------------------------------------------------------------------------------------------------------------------------------------------------

下面我们分析设置数据 activityMainBinding.setUser();

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        User user = new User("张三");
        activityMainBinding.setUser(user);
    }
}

//点击源码看到是个抽象类,那一定是其子类实现啦。其实核心逻辑在其子类ActivityMainBinderImpl类里面

//那我们看看ActivityMainBinderImpl的setUser()方法;代码很简单,给类里面的mUser赋值,再调用个notifyPropertyChanged()方法。

 

//点击notifyPropertyChanded方法;当你点击进去发现跟踪到最后是个onNotifyCallback()的抽象方法,貌似跟踪到了一个死胡同。这时我们可以看看他的父类 ViewDataBinding的代码。发现有个静态代码块

执行线程,看看线程代码最终执行了一个excutePendingBindings()方法

跟踪executePendingBindings()方法最后跟踪到一个executeBinding()抽象方法,那看看他子类ActivityMainBindingImpl实现这个方法代码,看到估计大家就比较清晰了,给我们创建的User赋值,获取name变量,调用TextViewBindingAdapter的setText方法,

 

点击setText方法,代码如下,这时一切就真相大白了。其实就是调用系统的TextView.setText()方法。

 

//到这里可能有人会问那TextView从哪里来的呢?其实很简单,代码如下

 

在构造方法获取的在解析Xml文件时,从根节点一个一个解析保存到bindings数组里面。根据tag信息字段对应节点是什么控件。

 

---------------------------------------------------------------------------数据驱动UI,实现双向绑定------------------------------------------------------

如果想数据变化UI跟随变,需要viewModel继承BaseObserable,在get方法使用@Bindable注解

在set方法调用notifyPorpertyChanged()方法 ,代码如下

public class User extends BaseObservable {
    private String name;



    public User(String name) {
        this.name = name;
    }



    @Bindable
    public String getName() {
        return name;
    }


    public void setName(String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }
}

我在activity测试代码。

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
//        setContentView(R.layout.activity_main);
        ActivityMainBinding activityMainBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);

        final User user = new User("张三");
        activityMainBinding.setUser(user);

       //测试数据双向绑定,数据驱动UI变化
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                user.setName("李四");
            }
        }, 5000);


    }
}

 

//我点击ViewDataBinding构造方法源码,打断点,发现通过回调接口FrameCallbackdoFrame方法执行线程的run方法,

//线程代码如下,最终会执行executePendingBindings()方法;

//这个方法最后会执行一个抽象方法executeBindings();

ActivityMainBingingImpl是ViewDataBing的子类,实现了executeBindings()方法,流程就跟上面分析一样了。

说白了就是通过回调接口实现数据双向绑定,最终还是调用系统的API设置数据更新Ui

//好了DataBinding源码分析就到这里。

最后附上一张我画的时序图

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值