DataBinding源码解析

在上一篇博客,我们是通过DataBindingUtil的.setContentView(this, R.layout.activity_main)方法来获取DataBinding对象的。那这个继承ViewDataBinding的Databinding对象是什么?它在整个架构中起到的作用是什么?the binding adapter什么时候调用setText()方法来设置text属性或者是调用setOnClickListener()方法来对点击事件添加一个监听?数据驱动具体是怎么回事儿?我们带着问题去相关的源码里面找一找答案。

ViewDataBinding类的一些内部类和方法

接口ObservableReference包含一些控制Listener和生命周期的操作,封装和定义了如下四个操作:

private interface ObservableReference<T> {
        WeakListener<T> getListener();
        void addListener(T target);
        void removeListener(T target);
        void setLifecycleOwner(LifecycleOwner lifecycleOwner);
    }

看几个重要的类:首先是静态内部类WeakListener里面定义了一个ObservableReference变量和int类型的绑定id和T类型的Observable,也是继承ViewDataBinding的引用——在当前类中有多个这种引用——class ViewDataBinding extends BaseObservable extends Observable。后面定义的WeakPropertyListener,WeakListListener,WeakMapListener,LiveDataListener都是针对具体情况的二次定义/实现:

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

        public WeakListener(ViewDataBinding binder, int localFieldId,
                ObservableReference<T> observable) {
            super(binder, sReferenceQueue);
            mLocalFieldId = localFieldId;
            mObservable = observable;
        }

        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            mObservable.setLifecycleOwner(lifecycleOwner);
        }

        public void setTarget(T object) {
            unregister();
            mTarget = object;
            if (mTarget != null) {
                mObservable.addListener(mTarget);
            }
        }

        public boolean unregister() {
            boolean unregistered = false;
            if (mTarget != null) {
                mObservable.removeListener(mTarget);
                unregistered = true;
            }
            mTarget = null;
            return unregistered;
        }

        public T getTarget() {
            return mTarget;
        }

        protected ViewDataBinding getBinder() {
            ViewDataBinding binder = get();
            if (binder == null) {
                unregister(); // The binder is dead
            }
            return binder;
        }
    }

再看一下类WeakProPertyListener——The callback that is called by Observable when an observable property has changed

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) {
            target.addOnPropertyChangedCallback(this);
        }

        @Override
        public void removeListener(Observable target) {
            target.removeOnPropertyChangedCallback(this);
        }

        @Override
        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
        }

        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            ViewDataBinding binder = mListener.getBinder();
            if (binder == null) {
                return;
            }
            Observable obj = mListener.getTarget();
            if (obj != sender) {
                return; // notification from the wrong object?
            }
            binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
        }
    }

那我们看一个属性绑定的静态实现类——继承”属性改变时候的回调方法的类”同时实现了”ObservableReference”接口。其中定义了一个WeakListener对象是根据ViewDataBinding对象和localFieldId和它本身(因为是实现了接口ObservableReference)来创建的,既然实现了接口我们看一下重写的那些方法可以发现getListener返回了构造函数创建的weakListener,addListener做的是将传入进来的Observable调用addPropertyChangedCallback,removeListener是observable调用自己的移除PropertyChangedCallback方法;换句话说这个接口WeakListener是定义了Observable Object触发View objects的功能封装。那这个WeakPropertyListener就是对于Observable的属性变化的时候的回调行为是binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId)。

具体看下WeakListener的setTarget(T object)unregister()

WeakListener<T> extends WeakReference<ViewDataBinding>
public void setTarget(T object) {
            unregister();
            mTarget = object;
            if (mTarget != null) {
                mObservable.addListener(mTarget);
            }
        }

WeakProPertyListener extends Observable.OnPropertyChangedCallback implements ObservableReference<Observable>
        @Override
        public void addListener(Observable target) {
            target.addOnPropertyChangedCallback(this);
        }
相当于 WeakListener<T> setTarget(T object)  -->  object.addOnPropertyChangedCallback(this);
public boolean unregister() {
            boolean unregistered = false;
            if (mTarget != null) {
                mObservable.removeListener(mTarget);
                unregistered = true;
            }
            mTarget = null;
            return unregistered;
        }

        @Override
        public void removeListener(Observable target) {
            target.removeOnPropertyChangedCallback(this);
        }
相当于 WeakListener<T> unregister()  -->  object.removeOnPropertyChangedCallback(this);

其他数据结构的Listener,其实和WeakPropertyListener差不多,就是回调的方式有些不同。一些相同的方法就用省略号代替了:

private static class WeakListListener extends ObservableList.OnListChangedCallback
            implements ObservableReference<ObservableList> {
        final WeakListener<ObservableList> mListener;

        public WeakListListener(ViewDataBinding binder, int localFieldId) {
            mListener = new WeakListener<ObservableList>(binder, localFieldId, this);
        }
       ...
        @Override
        public void onChanged(ObservableList sender) {
            ViewDataBinding binder = mListener.getBinder();
            if (binder == null) {
                return;
            }
            ObservableList target = mListener.getTarget();
            if (target != sender) {
                return; // We expect notifications only from sender
            }
            binder.handleFieldChange(mListener.mLocalFieldId, target, 0);
        }

        @Override
        public void onItemRangeChanged(ObservableList sender, int positionStart, int itemCount) {
            onChanged(sender);
        }

        @Override
        public void onItemRangeInserted(ObservableList sender, int positionStart, int itemCount) {
            onChanged(sender);
        }

        @Override
        public void onItemRangeMoved(ObservableList sender, int fromPosition, int toPosition,
                int itemCount) {
            onChanged(sender);
        }

        @Override
        public void onItemRangeRemoved(ObservableList sender, int positionStart, int itemCount) {
            onChanged(sender);
        }
    }

    private static class WeakMapListener extends ObservableMap.OnMapChangedCallback
            implements ObservableReference<ObservableMap> {
        final WeakListener<ObservableMap> mListener;

        public WeakMapListener(ViewDataBinding binder, int localFieldId) {
            mListener = new WeakListener<ObservableMap>(binder, localFieldId, this);
        }
      ...
        @Override
        public void onMapChanged(ObservableMap sender, Object key) {
            ViewDataBinding binder = mListener.getBinder();
            if (binder == null || sender != mListener.getTarget()) {
                return;
            }
            binder.handleFieldChange(mListener.mLocalFieldId, sender, 0);
        }
    }
private static class LiveDataListener implements Observer,
            ObservableReference<LiveData<?>> {
        final WeakListener<LiveData<?>> mListener;
        LifecycleOwner mLifecycleOwner;

        public LiveDataListener(ViewDataBinding binder, int localFieldId) {
            mListener = new WeakListener(binder, localFieldId, this);
        }
        ...
        @Override
        public void onChanged(@Nullable Object o) {
            ViewDataBinding binder = mListener.getBinder();
            binder.handleFieldChange(mListener.mLocalFieldId, mListener.getTarget(), 0);
        }
    }

Observable的属性变化的时候的回调具体来看一下:

private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
        if (mInLiveDataRegisterObserver) {
            // We're in LiveData registration, which always results in a field change
            // that we can ignore. The value will be read immediately after anyway, so
            // there is no need to be dirty.
            return;
        }
        boolean result = onFieldChange(mLocalFieldId, object, fieldId);
        if (result) {
            requestRebind();
        }
    }

接着我们看一下我上一篇博客的demo中登录页面实现里的ViewDataBinding类的子类是怎么实现onFieldChange方法的:

@Override
    protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
        switch (localFieldId) {
            case 0 :
                return onChangeUserName((android.databinding.ObservableField<java.lang.String>) object, fieldId);
            case 1 :
                return onChangeUserFormatOk((android.databinding.ObservableBoolean) object, fieldId);
            case 2 :
                return onChangeUserRememberPsw((android.databinding.ObservableBoolean) object, fieldId);
            case 3 :
                return onChangeUserPassword((android.databinding.ObservableField<java.lang.String>) object, fieldId);
            case 4 :
                return onChangeUserErrorNameTips((android.databinding.ObservableField<java.lang.String>) object, fieldId);
            case 5 :
                return onChangeUserErrorPswTips((android.databinding.ObservableField<java.lang.String>) object, fieldId);
        }
        return false;
    }
    private boolean onChangeUserName(android.databinding.ObservableField<java.lang.String> UserName, int fieldId) {
        if (fieldId == BR._all) {
            synchronized(this) {
                    mDirtyFlags |= 0x1L;   ######    0->1
            }
            return true;
        }
        return false;
    }

protected void requestRebind() {
        if (mContainingBinding != null) {
            mContainingBinding.requestRebind();
        } else {
            synchronized (this) {
                if (mPendingRebind) {
                    return;
                }
                mPendingRebind = true;
            }
            if (mLifecycleOwner != null) {
                Lifecycle.State state = mLifecycleOwner.getLifecycle().getCurrentState();
                if (!state.isAtLeast(Lifecycle.State.STARTED)) {
                    return; // wait until lifecycle owner is started
                }
            }
            if (USE_CHOREOGRAPHER) {
                mChoreographer.postFrameCallback(mFrameCallback);
            } else {
                mUIThreadHandler.post(mRebindRunnable);
            }
        }
    }

主要是运行抽象方法onFieldChange(int localFieldId, Object object, int fieldId)将mDirtyFlags进行运算之后重新绑定。如果是自布局included Binding Layout就调用它的requestRebind方法,如果不是就在下一帧运行重新绑定任务了。应该是要刷新对应的UI了吖?。?+ !。!感觉这里除了mDirtyFlags改变了有些可疑!有可能是刷新UI去了其他都是“常规操作”啊!。!而且从来没有出现过控件的什么代码啊?。!天了噜!不急!我们大致先了解了这几个类,再去ViewDataBinding类找找。

首先是构造函数

protected ViewDataBinding(DataBindingComponent bindingComponent, View root, int localFieldCount) {
        mBindingComponent = bindingComponent;
        mLocalFieldObservers = new WeakListener[localFieldCount];
        this.mRoot = root;
        if (Looper.myLooper() == null) {
            throw new IllegalStateException("DataBinding must be created in view's UI Thread");
        }
        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());
        }
    }

然后发现了静态块

private static final OnAttachStateChangeListener ROOT_REATTACHED_LISTENER;
static {
        if (VERSION.SDK_INT < VERSION_CODES.KITKAT) {
            ROOT_REATTACHED_LISTENER = null;
        } else {
            ROOT_REATTACHED_LISTENER = new OnAttachStateChangeListener() {
                @TargetApi(VERSION_CODES.KITKAT)
                @Override
                public void onViewAttachedToWindow(View v) {
                    // execute the pending bindings.
                    final ViewDataBinding binding = getBinding(v);
                    binding.mRebindRunnable.run();
                    v.removeOnAttachStateChangeListener(this);
                }

                @Override
                public void onViewDetachedFromWindow(View v) {
                }
            };
        }
    }

他会设置一个监听,在页面和窗口绑定之后从rootView里面取到当前的ViewDataBinding对象,调用里面的RebindRunnable

private final Runnable mRebindRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                mPendingRebind = false;
            }
            processReferenceQueue();

            if (VERSION.SDK_INT >= VERSION_CODES.KITKAT) {
                // Nested so that we don't get a lint warning in IntelliJ
                if (!mRoot.isAttachedToWindow()) {
                    // Don't execute the pending bindings until the View
                    // is attached again.
                    mRoot.removeOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
                    mRoot.addOnAttachStateChangeListener(ROOT_REATTACHED_LISTENER);
                    return;
                }
            }
            executePendingBindings();
        }
    };

这个Runnable主要是将待重新绑定状态mPendingRebind赋值为false,移除队列中所有绑定关系,运行待绑定的任务。


//将ViewDatabinding的队列清空,将里面的对于对象field in Model Obj的监听都移除
private static void processReferenceQueue() {
        Reference<? extends ViewDataBinding> ref;
        while ((ref = sReferenceQueue.poll()) != null) {
            if (ref instanceof WeakListener) {
                WeakListener listener = (WeakListener) ref;
                listener.unregister();
            }
        }
    }
/*mContainingBinding是对于有include布局ViewDataBinding对象的绑定对象,如果有的话需要运行他自己的executePendingBindings方法否则运行executeBindingsInternal方法,最后运行的是抽象方法executeBindings,在这个方法里面主要是将Observable Obj和他们的value清空,将绑定的那个对象赋值到这里,然后根据dirtyFlags和唯一的标识位将每一个Observable的关系都绑定好。*/
public void executePendingBindings() {
        if (mContainingBinding == null) {
            executeBindingsInternal();
        } else {
            mContainingBinding.executePendingBindings();
        }
    }

private void executeBindingsInternal() {
        if (mIsExecutingPendingBindings) {
            requestRebind();
            return;
        }
        if (!hasPendingBindings()) {
            return;
        }
        mIsExecutingPendingBindings = true;
        mRebindHalted = false;
        if (mRebindCallbacks != null) {
            mRebindCallbacks.notifyCallbacks(this, REBIND, null);

            // The onRebindListeners will change mPendingHalted
            if (mRebindHalted) {
                mRebindCallbacks.notifyCallbacks(this, HALTED, null);
            }
        }
        if (!mRebindHalted) {
            executeBindings();
            if (mRebindCallbacks != null) {
                mRebindCallbacks.notifyCallbacks(this, REBOUND, null);
            }
        }
        mIsExecutingPendingBindings = false;
    }

具体看下登录页面实现里的ViewDataBinding类的子类是怎么实现一个绑定方法的。
将Observable Obj和他们的value清空,将绑定的那个对象赋值到这里,然后调用updateRegistration方法:

@Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;
            mDirtyFlags = 0;
        }
        java.lang.String userPasswordGet = null;
        android.databinding.ObservableField<java.lang.String> userName = null;
        java.lang.String userErrorNameTipsGet = null;
        org.zy.demonew.twoway.action.LoginAction login = mLogin;
        android.databinding.adapters.TextViewBindingAdapter.AfterTextChanged userAfterTextChangeAndroidDatabindingAdaptersTextViewBindingAdapterAfterTextChanged = null;
        android.databinding.ObservableBoolean userFormatOk = null;
        java.lang.String userNameGet = null;
        android.databinding.ObservableBoolean userRememberPsw = null;
        boolean userFormatOkGet = false;
        java.lang.String userErrorPswTipsGet = null;
        android.databinding.ObservableField<java.lang.String> userPassword = null;
        boolean userRememberPswGet = false;
        org.zy.demonew.twoway.model.User user = mUser;
        android.databinding.ObservableField<java.lang.String> userErrorNameTips = null;
        android.databinding.ObservableField<java.lang.String> userErrorPswTips = null;

        if ((dirtyFlags & 0x1bfL) != 0) {


            if ((dirtyFlags & 0x181L) != 0) {    ######   448

                    if (user != null) {
                        // read user.name
                        userName = user.name;
                    }
                    updateRegistration(0, userName);


                    if (userName != null) {
                        // read user.name.get()
                        userNameGet = userName.get();
                    }
            }
            if ((dirtyFlags & 0x180L) != 0) {

......
}

看一下updateRegistration方法:

private boolean updateRegistration(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return unregisterFrom(localFieldId);
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            registerTo(localFieldId, observable, listenerCreator);
            return true;
        }
        if (listener.getTarget() == observable) {
            return false;//nothing to do, same object
        }
        unregisterFrom(localFieldId);
        registerTo(localFieldId, observable, listenerCreator);
        return true;
    }


private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
        @Override
        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
            return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
        }
    };
protected boolean updateRegistration(int localFieldId, Observable observable) {
        return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
    }

private boolean updateRegistration(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return unregisterFrom(localFieldId);
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            registerTo(localFieldId, observable, listenerCreator);
            return true;
        }
        if (listener.getTarget() == observable) {
            return false;//nothing to do, same object
        }
        unregisterFrom(localFieldId);
        registerTo(localFieldId, observable, listenerCreator);
        return true;
    }

protected void registerTo(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return;
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            listener = listenerCreator.create(this, localFieldId);
            mLocalFieldObservers[localFieldId] = listener;
            if (mLifecycleOwner != null) {
                listener.setLifecycleOwner(mLifecycleOwner);
            }
        }
        listener.setTarget(observable);
    }

mLocalFieldObservers用来存储WeakListener的数组,这个方法是根据你的localFieldId和对应的CreateWeakListener来创建WeakListener,并将Observable对象添加属性变化的监听,属性变化的时候能调用onPropertyChange方法,然后调用binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId)方法,然后是onFieldChange方法…

哇,果然漏了!在省略号里面,在方法executeBindings里面除了更新绑定关系和用新的对象赋值,还有根据dirtyFlags对控件进行对应处理。比如我在省略号下面的代码:

......
// batch finished
        if ((dirtyFlags & 0x19L) != 0) {
            // api target 1

            android.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView1, userFirstNameGet);
        }
        if ((dirtyFlags & 0x1cL) != 0) {
            // api target 1

            android.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView2, userLastNameGet);
        }
        if ((dirtyFlags & 0x1aL) != 0) {
            // api target 1

            android.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView3, mboundView3AndroidStringAgeFormatUserAge);
        }

也就是这个方法分成两块,一块是对数据更新和绑定关系更新还有就是对控件操作。

注意点
1. 实例化的DataBinding包含的一些绑定的布局:protected static class IncludedLayouts
2. BaseObservableField继承BaseObservable类主要有四个方法addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) ;removeOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback); notifyChange();notifyPropertyChanged(int fieldId)
3. fieldId是model用Bindable注释的变量的唯一标识,在自动生成的BR文件中
4. mLocalFieldId也是系统生成的,从0开始到最后一个绑定关系结束
5. 当dirtyFlag改变的时候只有对应的属性进行了重新绑定,其他地方不需要进行重新绑定

在MVVM中最重要的VM层是由安卓系统提供的工具帮我们生成和维护的,官方出品必出精品,完全放心使用。通过VM层对dirtyFlags进行与运算然后重新binding再根据新的dirtyFlags来控制执行相应的V层和M层的方法实现双向绑定。我们只要维护好我们的V层和M层就可以了,大大提高了开发效率和减少了代码量,结构上也清晰了很多。

本文原创,转载请注明链接https://blog.csdn.net/zhangwude2301
Demo下载地址

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值