美文网首页Android-Data Binding必看Android知识
Android Data Binding 系列(二) -- Bi

Android Data Binding 系列(二) -- Bi

作者: ConnorLin | 来源:发表于2016-07-13 13:30 被阅读614次

    写在前面

    上篇文章 Android Data Binding 系列(一) -- 详细介绍与使用 介绍了 Data Binding 的基础及其用法,本文接上篇,结合DataBindingDemo 来学习下 Data Binding 的实现。

    绑定实现

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

    绑定过程

    • 首先,会在父类(ViewDataBinding)中实例化回调或Handler,用于之后的绑定操作;
    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
    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
    // 用于动态重新绑定 Views
    private final Runnable mRebindRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                mPendingRebind = false;
            }
            .....
            executePendingBindings();
        }
    };
    
    • 最后,通过该Runnable会执行到 executePendingBindings() -> ... -> executeBindings(),在这里会执行绑定相关操作。
    @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;   // mDirtyFlags 变量更新的标志
            mDirtyFlags = 0;
        }
        .....
    }
    

    设置变量(数据对象)

    普通 Java bean 对象

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

    Observable 对象

    • 在设置变量时,会先调用 updateRegistration(..) 注册一个Observable对象的监听
    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() 中注册的

    @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)
    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 为何物?
    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的回调列表中

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

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

    更新(重新绑定)Observable对象

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

    • 回调过程
    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类中实现
    // 生成的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,这样,点击时就会触发相应的监听。

    这里以 DataBindingDemoEventActivity部分为例:

    • 生成的Binding类并实现View的事件监听
    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的事件监听
    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事件监听
    @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关联
    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监听
    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
    if (!mActivityViewStubBinding.viewStub.isInflated()) {
        mActivityViewStubBinding.viewStub.getViewStub().inflate();
    }
    

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

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

    这样,ViewStub绑定就结束了。

    本篇完,敬请期待下篇...


    我的简书账号是 ConnorLin,欢迎关注!

    我的简书专题是 Android开发技术分享,欢迎关注!

    相关文章

      网友评论

      本文标题:Android Data Binding 系列(二) -- Bi

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