Activity在inflate layout时,通过DataBindingUtil来生成绑定,从代码看,是遍历contentView得到View数组对象,然后通过数据绑定library生成对应的Binding类,含Views、变量、listeners等。生成类位于
build/intermediates/classes/debug/…package…/databinding/xxx.Java 下,具体如何生成这里暂不作深入。

绑定过程

  • 首先,会在父类(ViewDataBinding)中实例化回调或Handler,用于之后的绑定操作;
  1. private static final boolean USE_CHOREOGRAPHER = SDK_INT >= 16;

    if (USE_CHOREOGRAPHER) {
        mChoreographer = Choreographer.getInstance();
        mFrameCallback = new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                mRebindRunnable.run();
            }
        };
    } else {
        mFrameCallback = null;
        mUIThreadHandler = new Handler(Looper.myLooper());
    }
  • 接着,通过调用 mapBindings(…) 遍历布局以获得包含bound、includes、ID Views的数组对象,再依次赋给对应View
  1. final Object[] bindings = mapBindings(bindingComponent, root, 3, sIncludes, sViewsWithIds);
    this.mboundView0 = (Android.widget.LinearLayout) bindings[0];
    this.mboundView0.setTag(null);
  • 然后,调用 invalidateAll() -> requestRebind() -> … -> mRebindRunnable.run() – 执行 Runnable
  1. // 用于动态重新绑定 Views
    private final Runnable mRebindRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                mPendingRebind = false;
            }
            .....
            executePendingBindings();
        }
    };
  • 最后,通过该Runnable会执行到 executePendingBindings() -> … -> executeBindings(),在这里会执行绑定相关操作。
  1. @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;   // mDirtyFlags 变量更新的标志
            mDirtyFlags = 0;
        }
        .....
    }

设置变量(数据对象)

普通 Java bean 对象

  • 首先,通过mDirtyFlags标识变量(所有变量共用)
  1. synchronized(this) {
        mDirtyFlags |= 0x1L;
    }
  • 然后,调用 notifyPropertyChanged(…) 来通知更新(若有回调)
  1. public void notifyPropertyChanged(int fieldId) {
        if (mCallbacks != null) {
            mCallbacks.notifyCallbacks(this, fieldId, null);
        }
    }
  • 最后,调用 requestRebind() -> … -> executeBindings() 再次执行绑定操作,将数据更新到Views上
  1. @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;
            mDirtyFlags = 0;
        }
        .....
    }

Observable 对象

  • 在设置变量时,会先调用 updateRegistration(..) 注册一个Observable对象的监听
  1. public void setContact(com.connorlin.databinding.model.ObservableContact contact) {
        updateRegistration(0, contact);
        this.mContact = contact;
        synchronized(this) {
            mDirtyFlags |= 0x1L;
        }
        notifyPropertyChanged(BR.contact);
        super.requestRebind();
    }
  • 其他步骤同普通 Java bean 对象

ObservableFields 对象

  • 前期步骤同普通 Java Bean 对象
  • 与 Observable 对象不同的是,Observable对象的监听是在 executeBindings() 中注册的
  1. @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;
            mDirtyFlags = 0;
        }
        ...
        if ((dirtyFlags & 0xfL) != 0) {
            if ((dirtyFlags & 0xdL) != 0) {
                if (contact != null) {
                    // read contact.mName
                    mNameContact = contact.mName;
                }
                updateRegistration(0, mNameContact);

                if (mNameContact != null) {
                    // read contact.mName.get()
                    mNameContact1 = mNameContact.get();
                }
            }
            ...
        }
        ...
    }

注册Observable对象监听

  • 入口 updateRegistration(0, contact) :
  1. protected boolean updateRegistration(int localFieldId, Observable observable) {
        return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
    }

    private boolean updateRegistration(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        ...
        // 确保不重复监听,先移除再添加观察监听
        unregisterFrom(localFieldId);
        registerTo(localFieldId, observable, listenerCreator);
        return true;
    }

    protected void registerTo(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return;
        }

        // 创建对象监听并存到mLocalFieldObservers中
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            // CREATE_PROPERTY_LISTENER -> create(...)
            listener = listenerCreator.create(this, localFieldId);
            mLocalFieldObservers[localFieldId] = listener;
        }

        // 将监听绑定到Observable对象上
        listener.setTarget(observable);
    }

每个Observable对象都会添加一个观察监听,保存在数组 mLocalFieldObservers 中,并以 localFieldId 索引。

  • CREATE_PROPERTY_LISTENER 为何物?
  1. private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
        @Override
        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
            // 返回从WeakPropertyListener实例中获取的监听器(WeakListener)
            return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
        }
    }

    private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
            implements ObservableReference<Observable> {
        final WeakListener<Observable> mListener;

        public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {
            mListener = new WeakListener<Observable>(binder, localFieldId, this);
        }

        @Override
        public WeakListener<Observable> getListener() {
            return mListener;
        }

        @Override
        public void addListener(Observable target) {
            // WeakPropertyListener 继承于 Observable.OnPropertyChangedCallback,
            // 所以 this 其实就是 Observable对象的属性监听器
            target.addOnPropertyChangedCallback(this);
        }

        ...
    }

    private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
        private final ObservableReference<T> mObservable;
        protected final int mLocalFieldId;
        private T mTarget;

        ...

        public void setTarget(T object) {
            unregister();
            mTarget = object;
            if (mTarget != null) {
                // mObservable 是上面的 WeakPropertyListener对象
                // mTarget 是绑定到listener上得Observable对象
                mObservable.addListener(mTarget);
            }
        }

        ...
    }

CREATE_PROPERTY_LISTENER 实际上只是一个接口实例,注册时会调用它的create()方法创建一个弱引用listener,它的作用是将listener绑定到Observable对象上,
绑定时,会调用 listener.setTarget(…) 将Observable对象传给 WeakPropertyListener实例,然后,WeakPropertyListener 会为 Observable对象添加OnPropertyChangedCallback。

  • addOnPropertyChangedCallback实现

addOnPropertyChangedCallback 在 BaseObservable中实现,首先会实例化一个PropertyChangeRegistry对象,同时创建一个用来通知Observable对象重新绑定更新的回调CallbackRegistry.NotifierCallback。然后将 OnPropertyChangedCallback 添加到PropertyChangeRegistry的回调列表中

  1. @Override
    public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
        if (mCallbacks == null) {
            mCallbacks = new PropertyChangeRegistry();
        }
        mCallbacks.add(callback);
    }

这样,注册Observable对象的监听就完毕了。

更新(重新绑定)Observable对象

设置或更新Observable对象时都会调用notifyPropertyChanged()或notifyChange()来通知更新,那到底是如何更新的呢?

  • 回调过程
  1. public void notifyPropertyChanged(int fieldId) {
        // mCallbacks 是 PropertyChangeRegistry对象,在 addOnPropertyChangedCallback 时实例化
        // 如果注册了Observable对象监听,那么mCallbacks不为null
        if (mCallbacks != null) {
            mCallbacks.notifyCallbacks(this, fieldId, null);
        }
    }

    // baseLibrary
    private void notifyCallbacks(T sender, int arg, A arg2, int startIndex, int endIndex, long bits) {
        long bitMask = 1L;
        for(int i = startIndex; i < endIndex; ++i) {
            if((bits & bitMask) == 0L) {
                // mNotifier 是实例化PropertyChangeRegistry时创建的
                // mNotifier 即 CallbackRegistry.NotifierCallback
                this.mNotifier.onNotifyCallback(this.mCallbacks.get(i), sender, arg, arg2);
            }
            bitMask <<= 1;
        }
    }

    // PropertyChangeRegistry.NOTIFIER_CALLBACK
    public void onNotifyCallback(Observable.OnPropertyChangedCallback callback, Observable sender,
            int arg, Void notUsed) {
        // callback 是为Observable对象添加的OnPropertyChangedCallback,即WeakPropertyListener
        callback.onPropertyChanged(sender, arg);
    }

    // WeakPropertyListener
    public void onPropertyChanged(Observable sender, int propertyId) {
        // binder 即生成的Binding类对象
        ViewDataBinding binder = mListener.getBinder();
        ...
        binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
    }

    private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
        // onFieldChange 实现在生成的Binding类中
        boolean result = onFieldChange(mLocalFieldId, object, fieldId);
        if (result) {
            // 如果对象属性变化,将重新绑定
            requestRebind();
        }
    }

通过 notifyPropertyChanged 调用到 mNotifier 回调, mNotifier 通知OnPropertyChangedCallback Observable对象属性发生变化,然后在onPropertyChanged中又转给ViewDataBinding对象(生成的Binding类)处理。

  • 判断是否需要重新绑定并执行,在生成的Binding类中实现
  1. // 生成的Binding类中得方法
    protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
        // 如果变量不是Observable类型或没有添加 Bindable注解,就不会判断,直接返回false
        switch (localFieldId) {
            case 0 :
                return onChangeContact((com.connorlin.databinding.model.ObservableContact) object, fieldId);
        }
        return false;
    }

    private boolean onChangeContact(com.connorlin.databinding.model.ObservableContact contact, int fieldId) {
        switch (fieldId) {
            case BR.name: {
                synchronized(this) {
                        mDirtyFlags |= 0x4L;// 通过mDirtyFlags判断对象是否变化
                }
                return true;
            }
            ...
        }
        return false;
    }

至此,更新过程完毕。

整个注册与更新过程可以用一张流程图来概括:

事件处理

事件处理的原理很简单,在生成Binding类中会实现View事件的监听,在构造时实例化View的事件监听,然后在绑定时将事件监听对象赋值给对应View,这样,点击时就会触发相应的监听。

这里以 DataBindingDemo 中 EventActivity部分为例:

  • 生成的Binding类并实现View的事件监听
  1. public class ActivityEventBinding extends Android.databinding.ViewDataBinding
        implements Android.databinding.generated.callback.OnCheckedChangeListener.Listener,
            Android.databinding.generated.callback.OnClickListener.Listener {
        // Checkbox check监听
        private final Android.widget.CompoundButton.OnCheckedChangeListener mCallback3;
        private final Android.view.View.OnClickListener mCallback2;
        private final Android.view.View.OnClickListener mCallback1;
        // listeners
        private OnClickListenerImpl mAndroidViewViewOnCl;
        ...
        // Listener Stub Implementations
        public static class OnClickListenerImpl implements Android.view.View.OnClickListener{
            private com.connorlin.databinding.handler.EventHandler value;
            public OnClickListenerImpl setValue(com.connorlin.databinding.handler.EventHandler value) {
                this.value = value;
                return value == null ? null : this;
            }
            @Override
            public void onClick(Android.view.View arg0) {
                this.value.onClickFriend(arg0);
            }
        }
        ...
    }
  • 实例化View的事件监听
  1. public ActivityEventBinding(Android.databinding.DataBindingComponent bindingComponent, View root) {
        super(bindingComponent, root, 0);
        ...
        // listeners
        mCallback3 = new Android.databinding.generated.callback.OnCheckedChangeListener(this, 3);
        mCallback2 = new Android.databinding.generated.callback.OnClickListener(this, 2);
        mCallback1 = new Android.databinding.generated.callback.OnClickListener(this, 1);
        invalidateAll();
    }
  • 在执行绑定中绑定View事件监听
  1. @Override
    protected void executeBindings() {
        ...
        if ((dirtyFlags & 0x6L) != 0) {
            if (handler != null) {
                // read handler::onClickFriend
                AndroidViewViewOnCli = (((mAndroidViewViewOnCl == null)
                    ? (mAndroidViewViewOnCl = new OnClickListenerImpl()) : mAndroidViewViewOnCl).setValue(handler));
            }
        }
        // batch finished
        if ((dirtyFlags & 0x6L) != 0) {
            this.mboundView1.setOnClickListener(AndroidViewViewOnCli);
        }
        if ((dirtyFlags & 0x4L) != 0) {
            this.mboundView2.setOnClickListener(mCallback1);
            this.mboundView3.setOnClickListener(mCallback2);
            Android.databinding.adapters.CompoundButtonBindingAdapter.setListeners(
                this.mboundView4, mCallback3, (Android.databinding.InverseBindingListener)null);
        }
    }
  • 触发事件并执行

ViewStub

原理类似,只是利用 ViewStubProxy 来延迟绑定。

  • 使用layout中的ViewStub实例化一个ViewStubProxy对象赋给viewstub变量,并与Bingding关联
  1. public ActivityViewStubBinding(Android.databinding.DataBindingComponent bindingComponent, View root) {
        super(bindingComponent, root, 0);
        final Object[] bindings = mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds);
        ...
        this.viewStub = new Android.databinding.ViewStubProxy((Android.view.ViewStub) bindings[1]);
        this.viewStub.setContainingBinding(this);
        ...
    }
  • 实例化ViewStubProxy的同时会注册inflate监听
  1. private OnInflateListener mProxyListener = new OnInflateListener() {
        @Override
        public void onInflate(ViewStub stub, View inflated) {
            mRoot = inflated;
            mViewDataBinding = DataBindingUtil.bind(mContainingBinding.mBindingComponent,
                    inflated, stub.getLayoutResource());
            mViewStub = null;

            if (mOnInflateListener != null) {
                mOnInflateListener.onInflate(stub, inflated);
                mOnInflateListener = null;
            }
            mContainingBinding.invalidateAll();
            mContainingBinding.forceExecuteBindings();
        }
    };

    public ViewStubProxy(ViewStub viewStub) {
        mViewStub = viewStub;
        mViewStub.setOnInflateListener(mProxyListener);
    }
  • inflate ViewStub
  1. if (!mActivityViewStubBinding.viewStub.isInflated()) {
        mActivityViewStubBinding.viewStub.getViewStub().inflate();
    }

当ViewStub infate时,执行mProxyListener,其中会生成ViewStub的Binding,并强制执行主Binding重绑

  • 绑定ViewStub
  1. @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;
            mDirtyFlags = 0;
        }
        // batch finished
        if (viewStub.getBinding() != null) {
            viewStub.getBinding().executePendingBindings();
        }
    }

这样,ViewStub绑定就结束了。

Android的DataBinding原理介绍的更多相关文章

  1. android 编译的原理介绍

    http://blog.csdn.net/mr_raptor/article/details/7540066

  2. Android Animation学习(一) Property Animation原理介绍和API简介

    Android Animation学习(一) Property Animation介绍 Android Animation Android framework提供了两种动画系统: property a ...

  3. android MultiDex multidex原理原理下遇见的N个深坑(二)

    android MultiDex 原理下遇见的N个深坑(二) 这是在一个论坛看到的问题,其实你不知道MultiDex到底有多坑. 不了解的可以先看上篇文章:android MultiDex multi ...

  4. Android数据绑定DataBinding(二)入门篇

    前言 之前写了Android数据绑定DataBinding(一)入门篇,很简单的记录了如何使用DataBinding,其初衷是想要代码中的数据发生改变,不需要繁琐的setText等操作,在最后说到了只 ...

  5. Android数据绑定DataBinding(一)入门篇

    早上看到了一篇推文"还在使用繁琐的findViewById,跟着尝试了一下DataBinding,之前使用ButteKnife就已经干掉了findViewById.因为写过微信小程序,那种在 ...

  6. 03 Yarn 原理介绍

    Yarn 原理介绍 大纲: Hadoop 架构介绍 YARN 产生的背景 YARN 基础架构及原理   Hadoop的1.X架构的介绍   在1.x中的NameNodes只可能有一个,虽然可以通过Se ...

  7. 04 MapReduce原理介绍

    大数据实战(上) # MapReduce原理介绍 大纲: * Mapreduce介绍 * MapReduce2运行原理 * shuffle及排序    定义 * Mapreduce 最早是由googl ...

  8. Android四大基本组件介绍与生命周期

    Android四大基本组件介绍与生命周期 Android四大基本组件分别是Activity,Service服务,Content Provider内容提供者,BroadcastReceiver广播接收器 ...

  9. Android Testing学习01 介绍 测试测什么 测试的类型

    Android Testing学习01 介绍 测试测什么 测试的类型 Android 测试 测什么 1.Activity的生命周期事件 应该测试Activity的生命周期事件处理. 如果你的Activ ...

随机推荐

  1. Cloud TPU Demos(TensorFlow 云 TPU 样例代码)

    Cloud TPU Demos 这是一个Python脚本的集合,适合在开源TensorFlow和 Cloud TPU 上运行. 如果您想对模型做出任何修改或改进,请提交一个 PR ! https:// ...

  2. hibernate4整合spring3出现java.lang.NoClassDefFoundError: [Lorg/hibernate/engine/FilterDefinition;

    解决办法 原先:<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annota ...

  3. 关于return的一些了解

    写return是一种清晰的风格,可以防止一些意外的错误. 所以书上只说应该写,而不是必须写. 如果符合某个条件要退出的话,可以用return返回,否则可以不写这句代码的,当程序执行到"}&q ...

  4. 线性表 linear_list 顺序存储结构

    可以把线性表看作一串珠子 序列:指其中的元素是有序的 注意last和length变量的内在关系 注意:将元素所占的空间和表长合并为C语言的一个结构类型 静态分配的方式,分配给一个固定大小的存储空间之后 ...

  5. Java编写高质量代码改善程序的151个建议

    第一章  Java开发中通用的方法和准则 建议1:不要在常量和变量中出现易混淆的字母: (i.l.1:o.0等). 建议2:莫让常量蜕变成变量: (代码运行工程中不要改变常量值). 建议3:三元操作符 ...

  6. 77. Combinations(medium, backtrack, 重要, 弄了1小时)

    Given two integers n and k, return all possible combinations of k numbers out of 1 ... n. For exampl ...

  7. python学习之路前端-JavaScript

    JavaScript简介 JavaScript一种直译式脚本语言,是一种动态类型.弱类型.基于原型的语言,内置支持类型.它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本 ...

  8. Node.js Net 模块

    Node.js Net 模块提供了一些用于底层的网络通信的小工具,包含了创建服务器/客户端的方法,我们可以通过以下方式引入该模块: var net = require("net") ...

  9. PHP MySQL 简介

    PHP MySQL 简介 通过 PHP,您可以连接和操作数据库. MySQL 是跟 PHP 配套使用的最流行的开源数据库系统. 如果想学习更多 MySQL 知识可以查看本站MySQL 教程. MySQ ...

  10. ELK 6安装配置 nginx日志收集 kabana汉化

    #ELK 6安装配置 nginx日志收集 kabana汉化 #环境 centos 7.4 ,ELK 6 ,单节点 #服务端 Logstash 收集,过滤 Elasticsearch 存储,索引日志 K ...