AndroidX設計架構MVVM之DataBinding搭配LiveData的分析

AndroidX設計架構MVVM之DataBinding3.5.1結合LiveData2.1.0的分析
原文

AndroidX設計架構MVVM之ViewModel創建流程原理分析
AndroidX設計架構MVVM之ViewModel生命週期分析
AndroidX設計架構MVVM之LiveDatal生命週期及數據監聽分析
AndroidX設計架構MVVM之DataBinding搭配LiveData的分析
AndroidX設計架構MVVM之DataBinding+ViewModel+LiveData

本文只分析DataBinding結合LiveData對比原有的ObserveableField的共同點和區別,不做詳細使用說明
LiveData部分的分析請參考LiveDatal生命週期及數據監聽分析,設計到LiveData這部分的會在註釋中標識。

首先看一下代碼中綁定數據的入口,這些都是編譯過程中DataDinding自動生成的。

//DataBinding 動態綁定,屬性爲ObserveableField
 public void setUserNoLive(@Nullable com.lyldding.modulemvvm.bean.UserNoLiveBean UserNoLive) {
        this.mUserNoLive = UserNoLive;
        synchronized(this) {
            mDirtyFlags |= 0x8L;
        }
        //通知觀察者
        notifyPropertyChanged(BR.userNoLive);
        //分析點1
        super.requestRebind();
    }
    
    //ViewModel + LiveData模式
    public void setVMUser(@Nullable com.lyldding.modulemvvm.viewmodel.VMUser VMUser) {
        this.mVMUser = VMUser;
        synchronized(this) {
            mDirtyFlags |= 0x10L;
        }
         //通知觀察者
        notifyPropertyChanged(BR.vMUser);
         //分析點1
        super.requestRebind();
    }

分析點1:requestRebind()主要執行View的數據綁定,如果設置有生命週期的話,判斷處於非【onStart,onPause】區間則直接返回(那麼在onCreate中更新數據,什麼時機綁定數據呢?這一點文章結尾處分析)。這部分走正常流程,沒有設置生命週期的監聽。

protected void requestRebind() {
         // 如果View中有include 的view,也需要執行綁定數據
        if (mContainingBinding != null) {
            mContainingBinding.requestRebind();
        } else {
            final LifecycleOwner owner = this.mLifecycleOwner;
            //LifecycleOwner 不爲空則判斷View的狀態
            //不爲STARTED直接返回
            if (owner != null) {
                Lifecycle.State state = owner.getLifecycle().getCurrentState();
                if (!state.isAtLeast(Lifecycle.State.STARTED)) {
                    return; // wait until lifecycle owner is started
                }
            }
            synchronized (this) {
                if (mPendingRebind) {
                    return;
                }
                mPendingRebind = true;
            }
            //SDK_INT >= 16,則在下一幀運行,最終執行的都是mRebindRunnable
            if (USE_CHOREOGRAPHER) {
                mChoreographer.postFrameCallback(mFrameCallback);
            } else {
                //分析點2
                mUIThreadHandler.post(mRebindRunnable);
            }
        }
    }
         //mFrameCallback 示例
             mFrameCallback = new Choreographer.FrameCallback() {
                @Override
                public void doFrame(long frameTimeNanos) {
                    //分析點2
                    mRebindRunnable.run();
                }
            };

分析點2:mRebindRunnable()先移除所有的觀察者,然後再加觀察者並綁定數據。

 private final Runnable mRebindRunnable = new Runnable() {
        @Override
        public void run() {
            synchronized (this) {
                mPendingRebind = false;
            }
            //移除所有的觀察者
            processReferenceQueue();
            //sdk >=19,判斷view是否附加到窗口,如果沒有就設置監聽,
            //當附加到窗口後,再執行一遍mRebindRunnable 
            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;
                }
            }
            //分析點3
            executePendingBindings();
        }
    };

分析點3:沒什麼特別,最終執行到 executeBindings();

   public void executePendingBindings() {
        if (mContainingBinding == null) {
            executeBindingsInternal();
        } else {
            mContainingBinding.executePendingBindings();
        }
    }

 private void executeBindingsInternal() {
        //如果上一次沒有執行結束,則本次的數據綁定則一直循環等待
        if (mIsExecutingPendingBindings) {
            requestRebind();
            return;
        }
        if (!hasPendingBindings()) {
            return;
        }
        mIsExecutingPendingBindings = true;
        mRebindHalted = false;
        //這裏沒有添加Rebind的回調,所以爲空
        if (mRebindCallbacks != null) {
            mRebindCallbacks.notifyCallbacks(this, REBIND, null);

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

分析點4:主要的工作爲設置點擊事件的監聽,更新註冊數據的觀察者,綁定view展示的數據。

  @Override
    protected void executeBindings() {
        long dirtyFlags = 0;
        synchronized(this) {
            dirtyFlags = mDirtyFlags;
            mDirtyFlags = 0;
        }
        androidx.databinding.ObservableField<java.lang.String> userNoLiveName = null;
        java.lang.String vMUserUserInfoAge = null;
        com.lyldding.modulemvvm.MvvmMainActivity eventListener = mEventListener;
        com.lyldding.modulemvvm.bean.UserBean vMUserUserInfoGetValue = null;
        com.lyldding.modulemvvm.bean.UserNoLiveBean userNoLive = mUserNoLive;
        androidx.lifecycle.MutableLiveData<com.lyldding.modulemvvm.bean.UserBean> vMUserUserInfo = null;
        com.lyldding.modulemvvm.viewmodel.VMUser vMUser = mVMUser;
        java.lang.String vMUserUserInfoName = null;
        android.view.View.OnClickListener eventListenerOnClickAndroidViewViewOnClickListener = null;
        java.lang.String userNoLiveNameGet = null;

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


                //分析點5
                //點擊事件不爲空則設置點擊事件,
                if (eventListener != null) {
                    // read eventListener::onClick
                    eventListenerOnClickAndroidViewViewOnClickListener = (((mEventListenerOnClickAndroidViewViewOnClickListener == null) ? (mEventListenerOnClickAndroidViewViewOnClickListener = new OnClickListenerImpl()) : mEventListenerOnClickAndroidViewViewOnClickListener).setValue(eventListener));
                }
        }
        if ((dirtyFlags & 0x29L) != 0) {



                if (userNoLive != null) {
                    // read userNoLive.name
                    userNoLiveName = userNoLive.name;
                }
                //分析點6  更新觀察者
                //這裏是數據對象的ObservableField類屬性
                //如果有多個ObservableField類屬性的話,會生成多個updateRegistration(localFieldId, userNoLiveXXX);
                updateRegistration(0, userNoLiveName);


                if (userNoLiveName != null) {
                    // read userNoLive.name.get()
                    userNoLiveNameGet = userNoLiveName.get();
                }
        }
        if ((dirtyFlags & 0x32L) != 0) {



                if (vMUser != null) {
                    // read vMUser.userInfo
                    vMUserUserInfo = vMUser.getUserInfo();
                }
                 //分析點7 更新觀察者
           
                //這裏是LiveData數據對象
                updateLiveDataRegistration(1, vMUserUserInfo);


                if (vMUserUserInfo != null) {
                    // read vMUser.userInfo.getValue()
                    vMUserUserInfoGetValue = vMUserUserInfo.getValue();
                }


                if (vMUserUserInfoGetValue != null) {
                    // read vMUser.userInfo.getValue().age
                    vMUserUserInfoAge = vMUserUserInfoGetValue.getAge();
                    // read vMUser.userInfo.getValue().name
                    vMUserUserInfoName = vMUserUserInfoGetValue.getName();
                }
        }
        // batch finished
        if ((dirtyFlags & 0x32L) != 0) {
            // api target 1
            //設置View展示數據
            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.age, vMUserUserInfoAge);
            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.name, vMUserUserInfoName);
        }
        if ((dirtyFlags & 0x29L) != 0) {
            // api target 1
            //設置View展示數據
            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.nameNoLive, userNoLiveNameGet);
        }
        if ((dirtyFlags & 0x24L) != 0) {
            // api target 1
            //設置點擊事件監聽
           this.title.setOnClickListener(eventListenerOnClickAndroidViewViewOnClickListener);
        }
    }

分析點5:其實就對原有對象的的public 點擊方法進行了包裝轉化。

// Listener Stub Implementations
    public static class OnClickListenerImpl implements android.view.View.OnClickListener{
        private com.lyldding.modulemvvm.MvvmMainActivity value;
        public OnClickListenerImpl setValue(com.lyldding.modulemvvm.MvvmMainActivity value) {
            this.value = value;
            return value == null ? null : this;
        }
        @Override
        public void onClick(android.view.View arg0) {
            //真正執行的地方
            this.value.onClick(arg0); 
        }
    }

分析點6和分析點7:這部分就是ObservableField和LiveData區別的開始,注意傳入的方法字段類型不一樣,不過流程相似的。下面就對比着把流程走完。

   /**
     * @hide
     */
     //ObservableField  傳入的字段爲Observable 
    protected boolean updateRegistration(int localFieldId, Observable observable) {
        //分析點8
        return updateRegistration(localFieldId, observable, CREATE_PROPERTY_LISTENER);
    }
    
 /**
     * @hide
     */
     //LiveData 傳入的字段爲Observable  LiveData
    protected boolean updateLiveDataRegistration(int localFieldId, LiveData<?> observable) {
        mInLiveDataRegisterObserver = true;
        try {
         //分析點9
            return updateRegistration(localFieldId, observable, CREATE_LIVE_DATA_LISTENER);
        } finally {
            mInLiveDataRegisterObserver = false;
        }
    }

分析點8和分析點9:也就是CREATE_PROPERTY_LISTENER和CREATE_LIVE_DATA_LISTENER的區別。接下來先看兩個CREATE_XXXX的區別,在分析updateRegistration();

兩個CREATE_XXXX的區別:只是創建類不同

 private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
        @Override
        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
            //分析點10 WeakPropertyListener
            return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
        }
    };

 private static final CreateWeakListener CREATE_LIVE_DATA_LISTENER = new CreateWeakListener() {
        @Override
        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
            //分析點11 LiveDataListener
            return new LiveDataListener(viewDataBinding, localFieldId).getListener();
        }
    };

updateRegistration():unregisterFrom先註銷原有觀察者,registerTo再註冊一個當前的觀察者。

//
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);
        //註冊觀察者
        //分析點12,這部分放到下面
        registerTo(localFieldId, observable, listenerCreator);
        return true;
    }

分析點10和分析點11:也就是WeakPropertyListener和LiveDataListener的區別。注意接口ObservableReference傳入的泛型類型,接下來分別分析一下兩個類

WeakPropertyListener

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

        public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {
            //分析點13  創建一個WeakListener
            mListener = new WeakListener<Observable>(binder, localFieldId, this);
        }
        
        @Override
        //返回WeakListener
        public WeakListener<Observable> getListener() {
            return mListener;
        }

        @Override
          //這個地方要注意,下文會提到
        public void addListener(Observable target) {
            //ObservableField添加數據屬性變化的監聽
            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?
            }
            //view重新綁定當前屬性值
            binder.handleFieldChange(mListener.mLocalFieldId, sender, propertyId);
        }
    }
    
    //view重新綁定當前屬性值
  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) {
          //view重新綁定當前屬性值
           //忘記的返回查看分析點1
            requestRebind();
        }
    }

LiveDataListener:這個類中能看到單獨使用LiveData時候的影子,不熟悉的話請參考LiveDatal生命週期及數據監聽分析

private static class LiveDataListener implements Observer,
            ObservableReference<LiveData<?>> {
        final WeakListener<LiveData<?>> mListener;
        LifecycleOwner mLifecycleOwner;

        public LiveDataListener(ViewDataBinding binder, int localFieldId) {
         //分析點13   創建一個WeakListener
            mListener = new WeakListener(binder, localFieldId, this);
        }

        @Override
           //這個地方要注意,下文會提到
        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            LifecycleOwner owner = (LifecycleOwner) lifecycleOwner;
            LiveData<?> liveData = mListener.getTarget();
            if (liveData != null) {
                if (mLifecycleOwner != null) {
                    //移除觀察者
                    liveData.removeObserver(this);
                }
                if (lifecycleOwner != null) {
                    //添加生命週期觀察者,並監聽數據變化
                    liveData.observe(owner, this);
                }
            }
            mLifecycleOwner = owner;
        }

        @Override
        //返回WeakListener
        public WeakListener<LiveData<?>> getListener() {
            return mListener;
        }

        @Override
          //這個地方要注意,下文會提到
        public void addListener(LiveData<?> target) {
            if (mLifecycleOwner != null) {
               //livedata添加生命週期觀察者,並監聽數據變化
                target.observe(mLifecycleOwner, this);
            }
        }

        @Override
        public void removeListener(LiveData<?> target) {
            target.removeObserver(this);
        }

        @Override
        //LiveData 數據變化時的回調
        public void onChanged(@Nullable Object o) {
            ViewDataBinding binder = mListener.getBinder();
            if (binder != null) {
                //view重新綁定當前屬性值
                binder.handleFieldChange(mListener.mLocalFieldId, mListener.getTarget(), 0);
            }
        }
    }
    
    //view重新綁定當前屬性值
 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) {
         //view重新綁定當前屬性值
           //忘記的返回查看分析點1
            requestRebind();
        }
    }

分析點13:看一下WeakListener到底是什麼?WeakListener繼承WeakReference,其實就是一個弱引用類,持有一個實現ObservableReference接口對象observable,並提供設置LifecycleOwner和監聽的方法。

private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
        private final ObservableReference<T> mObservable;
        protected final int mLocalFieldId;
        private T mTarget;
        //構造函數傳入的有ViewDataBinding ,屬性FieldId,
        //一個實現ObservableReference接口對象observable
        public WeakListener(ViewDataBinding binder, int localFieldId,
                ObservableReference<T> observable) {
            super(binder, sReferenceQueue);
            mLocalFieldId = localFieldId;
            mObservable = observable;
        }
        //WeakListener 設置LifecycleOwner
        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            //ObservableField 和LiveData類型的實現方式不一樣
            //可以回看分析點10 和分析點11
            mObservable.setLifecycleOwner(lifecycleOwner);
        }
        //註冊
        //這個地方要注意,下文會提到
        public void setTarget(T object) {
            unregister();
            mTarget = object;
            if (mTarget != null) {
            //ObservableField 和LiveData類型的實現方式不一樣
            //可以回看分析點10 和分析點11
                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;
        }
    }

分析點12:上面的準備工作都分析了,分析點8和9創建了CreateWeakListener,在這部分創建一個WeakListener對象(見分析點13),

protected void registerTo(int localFieldId, Object observable,
            CreateWeakListener listenerCreator) {
        if (observable == null) {
            return;
        }
        WeakListener listener = mLocalFieldObservers[localFieldId];
        if (listener == null) {
            //創建WeakListener, 
            listener = listenerCreator.create(this, localFieldId);
            mLocalFieldObservers[localFieldId] = listener;
            if (mLifecycleOwner != null) {
                //WeakListener的setLifecycleOwner
               //可以回看分析點13
                listener.setLifecycleOwner(mLifecycleOwner);
            }
        }
        //註冊觀察者
        //WeakListener的setTarget,讓持有的對象註冊觀察者
        //可以回看分析點13
        listener.setTarget(observable);
    }

到此:DataBinding中對使用ObservableField和LiveData類型的數據動態綁定更新就結束。

分析點1:遺留問題,假如Databinding 設置了LifecycleOwner ,那麼在onCreate中更新數據,什麼時機綁定數據呢?

這時候就在OnStart中綁定數據

解鈴還須繫鈴人,看ViewDataBinding的setLifecycleOwner方法。

@MainThread
    public void setLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) {
        if (mLifecycleOwner == lifecycleOwner) {
            return;
        }
        //移除mOnStartListener觀察者
        if (mLifecycleOwner != null) {
            mLifecycleOwner.getLifecycle().removeObserver(mOnStartListener);
        }
        mLifecycleOwner = lifecycleOwner;
        if (lifecycleOwner != null) {
            if (mOnStartListener == null) {
               //這裏創建mOnStartListener觀察者
                mOnStartListener = new OnStartListener(this);
            }
             //添加mOnStartListener觀察者
            lifecycleOwner.getLifecycle().addObserver(mOnStartListener);
        }
        for (WeakListener<?> weakListener : mLocalFieldObservers) {
            if (weakListener != null) {
                //可以回看分析點13
                weakListener.setLifecycleOwner(lifecycleOwner);
            }
        }
    }
    
 static class OnStartListener implements LifecycleObserver {
        final WeakReference<ViewDataBinding> mBinding;
        private OnStartListener(ViewDataBinding binding) {
            //創建binder的弱引用
            mBinding = new WeakReference<>(binding);
        }
       //在view的生命週期爲onStart中回調
        @OnLifecycleEvent(Lifecycle.Event.ON_START)
        public void onStart() {
            ViewDataBinding dataBinding = mBinding.get();
            if (dataBinding != null) {
                //執行數據綁定
                //可以回看分析點3
                dataBinding.executePendingBindings();
            }
        }
    }

總結:從上面的分析可知,在使用BindingImpl設置綁定ViewModel數據時,會執行executeBindings(),executeBindings()中會註冊一個數據變化的觀察者observer並且更新view中的數據,每當數據發生變化時(ObservableField.xx.set() 和LiveData.setValue),都會回調observer的方法,進而重新執行executeBindings()。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章