美文网首页
DataBinding浅析

DataBinding浅析

作者: MIRROR1217 | 来源:发表于2021-06-30 23:31 被阅读0次

    目前工程使用了DataBinding,感觉还可以,但是有时候确实不好调试,运行的时候最好看下错误日志,可以使用gradle assembleDebug --info编译查看,可以看到比较明显的日志。然后呢,抽空看了下DataBinding的源码,也看了下其他同学对于DataBinding的一些分析,结合自己的一些看法,对DataBinding做个总结。

    1.DataBinding的作用?

    在MVC模式中,用不用DataBinding都可以,不会有明显的变化。因为UI的变化和数据的变化都在Activity中。
    但是在MVP和MVVM模式中,如果使用了DataBinding,你会感觉很愉悦的。不是说不能用,配合LiveData也可以,但是感觉很麻烦,也是一些重复性的工作。【好的技术就是用来偷懒的!-鲁迅】
    DataBinding的核心作用就一个,和UI组件相互绑定,能直接通知对方刷新,其他的作用都是顺带的。

    2.DataBinding的原理?

    下面来分析下DataBinding的原理,这里先做总结:

    DataBinding通过apt技术生成编译期的代码,实现对View的绑定和对数据Observable的监听,而对View的监听则是通过setTextWatcher来实现的。

    上面其实的说的比较笼统,我们下面来具体分析

    一.DataBinding编译期间通过apt和javapoet技术生成代码

    会生成几个重要的文件,先看生成的layout文件


    image.png

    说下它们的作用,先说下面那个


    image.png
    这个主要是生成layout文件,能被xml解析的。
    再看第一个
    image.png

    可以看到,它是保存原layout文件保存可一些信息,比如是否有merge、时候双向绑定等。
    再看生成的java文件,如下


    image.png
    里面有几个重要文件,DataBinding里面的核心代码就在它们里面
    ActivityMainBinding、BR、DataBinderMapperImpl、ActivityMainBindingImpl等。
    二.从DataBinding.setContentView分析源码:
    class MainActivity : AppCompatActivity() {
    
    
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            val databind = DataBindingUtil.setContentView<ActivityMainBinding>(this,R.layout.activity_main)
            val person = Person()
            person.userName.set("1111111")
            databind.person = person
    //        setContentView(R.layout.activity_main)
        }
    }
    

    追踪DataBinding源码:

    public class DataBindingUtil {
    private static DataBinderMapper sMapper = new DataBinderMapperImpl();
        private static DataBindingComponent sDefaultComponent = null;
    public static <T extends ViewDataBinding> T setContentView(@NonNull Activity activity,
                int layoutId) {
            return setContentView(activity, layoutId, sDefaultComponent);
        }
    
    public static <T extends ViewDataBinding> T setContentView(@NonNull Activity activity,
                int layoutId, @Nullable DataBindingComponent bindingComponent) {
            activity.setContentView(layoutId);
            View decorView = activity.getWindow().getDecorView();
            ViewGroup contentView = (ViewGroup) decorView.findViewById(android.R.id.content);
            return bindToAddedViews(bindingComponent, contentView, 0, layoutId);
        }
    
    private static <T extends ViewDataBinding> T bindToAddedViews(DataBindingComponent component,
                ViewGroup parent, int startChildren, int layoutId) {
            final int endChildren = parent.getChildCount();
            final int childrenAdded = endChildren - startChildren;
            if (childrenAdded == 1) {
                final View childView = parent.getChildAt(endChildren - 1);
                return bind(component, childView, layoutId);
            } else {
                final View[] children = new View[childrenAdded];
                for (int i = 0; i < childrenAdded; i++) {
                    children[i] = parent.getChildAt(i + startChildren);
                }
                return bind(component, children, layoutId);
            }
        }
    
      static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View[] roots,
                int layoutId) {
            return (T) sMapper.getDataBinder(bindingComponent, roots, layoutId);
        }
    }
    

    内部还是调用了Activity.setContentVIew()方法,然后返回一个ViewDataBinding。然后可以看到,遍历View的个数,调用bind()方法。而sMapper是DataBinderMapperImpl,所有我们看下其内部:

    public class DataBinderMapperImpl extends DataBinderMapper {
      private static final int LAYOUT_ACTIVITYMAIN = 1;
    
      private static final SparseIntArray INTERNAL_LAYOUT_ID_LOOKUP = new SparseIntArray(1);
    
      static {
        INTERNAL_LAYOUT_ID_LOOKUP.put(com.example.databingtest2.R.layout.activity_main, LAYOUT_ACTIVITYMAIN);
      }
    
      @Override
      public ViewDataBinding getDataBinder(DataBindingComponent component, View view, int layoutId) {
        int localizedLayoutId = INTERNAL_LAYOUT_ID_LOOKUP.get(layoutId);
        if(localizedLayoutId > 0) {
          final Object tag = view.getTag();
          if(tag == null) {
            throw new RuntimeException("view must have a tag");
          }
          switch(localizedLayoutId) {
            case  LAYOUT_ACTIVITYMAIN: {
              if ("layout/activity_main_0".equals(tag)) {
                return new ActivityMainBindingImpl(component, view);
              }
              throw new IllegalArgumentException("The tag for activity_main is invalid. Received: " + tag);
            }
          }
        }
        return null;
      }
    
      @Override
      public ViewDataBinding getDataBinder(DataBindingComponent component, View[] views, int layoutId) {
        if(views == null || views.length == 0) {
          return null;
        }
        int localizedLayoutId = INTERNAL_LAYOUT_ID_LOOKUP.get(layoutId);
        if(localizedLayoutId > 0) {
          final Object tag = views[0].getTag();
          if(tag == null) {
            throw new RuntimeException("view must have a tag");
          }
          switch(localizedLayoutId) {
          }
        }
        return null;
      }
    
      @Override
      public int getLayoutId(String tag) {
        if (tag == null) {
          return 0;
        }
        Integer tmpVal = InnerLayoutIdLookup.sKeys.get(tag);
        return tmpVal == null ? 0 : tmpVal;
      }
    
      @Override
      public String convertBrIdToString(int localId) {
        String tmpVal = InnerBrLookup.sKeys.get(localId);
        return tmpVal;
      }
    
      @Override
      public List<DataBinderMapper> collectDependencies() {
        ArrayList<DataBinderMapper> result = new ArrayList<DataBinderMapper>(1);
        result.add(new androidx.databinding.library.baseAdapters.DataBinderMapperImpl());
        return result;
      }
    
      private static class InnerBrLookup {
        static final SparseArray<String> sKeys = new SparseArray<String>(2);
    
        static {
          sKeys.put(0, "_all");
          sKeys.put(1, "person");
        }
      }
    
      private static class InnerLayoutIdLookup {
        static final HashMap<String, Integer> sKeys = new HashMap<String, Integer>(1);
    
        static {
          sKeys.put("layout/activity_main_0", com.example.databingtest2.R.layout.activity_main);
        }
      }
    }
    

    最后返回的是ActivityMainBindingImpl构造方法,继续追踪:

    public class ActivityMainBindingImpl extends ActivityMainBinding  {
    
        @Nullable
        private static final androidx.databinding.ViewDataBinding.IncludedLayouts sIncludes;
        @Nullable
        private static final android.util.SparseIntArray sViewsWithIds;
        static {
            sIncludes = null;
            sViewsWithIds = null;
        }
        // views
        @NonNull
        private final androidx.constraintlayout.widget.ConstraintLayout mboundView0;
        // variables
        // values
        // listeners
        // Inverse Binding Event Handlers
        private androidx.databinding.InverseBindingListener text1androidTextAttrChanged = new androidx.databinding.InverseBindingListener() {
            @Override
            public void onChange() {
                // Inverse of person.userName.get()
                //         is person.userName.set((java.lang.String) callbackArg_0)
                java.lang.String callbackArg_0 = androidx.databinding.adapters.TextViewBindingAdapter.getTextString(text1);
                // localize variables for thread safety
                // person
                com.example.databingtest2.Person person = mPerson;
                // person.userName
                androidx.databinding.ObservableField<java.lang.String> personUserName = null;
                // person.userName.get()
                java.lang.String personUserNameGet = null;
                // person != null
                boolean personJavaLangObjectNull = false;
                // person.userName != null
                boolean personUserNameJavaLangObjectNull = false;
    
    
    
                personJavaLangObjectNull = (person) != (null);
                if (personJavaLangObjectNull) {
    
    
                    personUserName = person.getUserName();
    
                    personUserNameJavaLangObjectNull = (personUserName) != (null);
                    if (personUserNameJavaLangObjectNull) {
    
    
    
    
                        personUserName.set(((java.lang.String) (callbackArg_0)));
                    }
                }
            }
        };
    
        public ActivityMainBindingImpl(@Nullable androidx.databinding.DataBindingComponent bindingComponent, @NonNull View root) {
            this(bindingComponent, root, mapBindings(bindingComponent, root, 2, sIncludes, sViewsWithIds));
        }
        private ActivityMainBindingImpl(androidx.databinding.DataBindingComponent bindingComponent, View root, Object[] bindings) {
            super(bindingComponent, root, 1
                , (android.widget.TextView) bindings[1]
                );
            this.mboundView0 = (androidx.constraintlayout.widget.ConstraintLayout) bindings[0];// ---> ①
            this.mboundView0.setTag(null);
            this.text1.setTag(null);
            setRootTag(root);
            // listeners
            invalidateAll();// ---->②
        }
    
        @Override
        public void invalidateAll() {
            synchronized(this) {
                    mDirtyFlags = 0x4L;
            }
            requestRebind();//----->三
        }
    
        @Override
        public boolean hasPendingBindings() {
            synchronized(this) {
                if (mDirtyFlags != 0) {
                    return true;
                }
            }
            return false;
        }
    
        @Override
        public boolean setVariable(int variableId, @Nullable Object variable)  {
            boolean variableSet = true;
            if (BR.person == variableId) {
                setPerson((com.example.databingtest2.Person) variable);
            }
            else {
                variableSet = false;
            }
                return variableSet;
        }
    
        public void setPerson(@Nullable com.example.databingtest2.Person Person) {
            this.mPerson = Person;
            synchronized(this) {
                mDirtyFlags |= 0x2L;
            }
            notifyPropertyChanged(BR.person);
            super.requestRebind();
        }
    
        @Override
        protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
            switch (localFieldId) {
                case 0 :
                    return onChangePersonUserName((androidx.databinding.ObservableField<java.lang.String>) object, fieldId);
            }
            return false;
        }
        private boolean onChangePersonUserName(androidx.databinding.ObservableField<java.lang.String> PersonUserName, int fieldId) {
            if (fieldId == BR._all) {
                synchronized(this) {
                        mDirtyFlags |= 0x1L;
                }
                return true;
            }
            return false;
        }
    
        @Override
        protected void executeBindings() {
            long dirtyFlags = 0;
            synchronized(this) {
                dirtyFlags = mDirtyFlags;
                mDirtyFlags = 0;
            }
            com.example.databingtest2.Person person = mPerson;
            int personColor = 0;
            androidx.databinding.ObservableField<java.lang.String> personUserName = null;
            java.lang.String personUserNameGet = null;
    
            if ((dirtyFlags & 0x7L) != 0) {
    
    
                if ((dirtyFlags & 0x6L) != 0) {
    
                        if (person != null) {
                            // read person.color
                            personColor = person.getColor();
                        }
                }
    
                    if (person != null) {
                        // read person.userName
                        personUserName = person.getUserName();
                    }
                    updateRegistration(0, personUserName);
    
    
                    if (personUserName != null) {
                        // read person.userName.get()
                        personUserNameGet = personUserName.get();
                    }
            }
            // batch finished
            if ((dirtyFlags & 0x6L) != 0) {
                // api target 1
    
                com.example.databingtest2.DataBindingAdapterExtKt.setTextViewColor(this.text1, personColor);
            }
            if ((dirtyFlags & 0x7L) != 0) {
                // api target 1
    
                androidx.databinding.adapters.TextViewBindingAdapter.setText(this.text1, personUserNameGet);
            }
            if ((dirtyFlags & 0x4L) != 0) {
                // api target 1
    
                androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.text1, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, text1androidTextAttrChanged);
            }
        }
        // Listener Stub Implementations
        // callback impls
        // dirty flag
        private  long mDirtyFlags = 0xffffffffffffffffL;
        /* flag mapping
            flag 0 (0x1L): person.userName
            flag 1 (0x2L): person
            flag 2 (0x3L): null
        flag mapping end*/
        //end
    }
    

    ActivityMainBindingImpl继承ActivityMainBinding,所以可以返回ActivityMainBinding结束了。

    三.DataBinding数据和View的相互绑定

    ActivityMainBindingImpl.invalidateAll() -->ActivityMainBindingImpl.requestRebind() -->
    ViewDataBinding.executePendingBindings() --->ViewDataBinding.executeBindingsInternal()--->
    ActivityMainBindingImpl.executeBindings(),我们看下executeBindings()源码:

     @Override
        protected void executeBindings() {
            long dirtyFlags = 0;
            synchronized(this) {
                dirtyFlags = mDirtyFlags;
                mDirtyFlags = 0;
            }
            com.example.databingtest2.Person person = mPerson;
            int personColor = 0;
            androidx.databinding.ObservableField<java.lang.String> personUserName = null;
            java.lang.String personUserNameGet = null;
    
            if ((dirtyFlags & 0x7L) != 0) {
    
    
                if ((dirtyFlags & 0x6L) != 0) {
    
                        if (person != null) {
                            // read person.color
                            personColor = person.getColor();
                        }
                }
    
                    if (person != null) {
                        // read person.userName
                        personUserName = person.getUserName();
                    }
                    updateRegistration(0, personUserName);
    
    
                    if (personUserName != null) {
                        // read person.userName.get()
                        personUserNameGet = personUserName.get();
                    }
            }
            // batch finished
            if ((dirtyFlags & 0x6L) != 0) {
                // api target 1
    
                com.example.databingtest2.DataBindingAdapterExtKt.setTextViewColor(this.text1, personColor);
            }
            if ((dirtyFlags & 0x7L) != 0) {
                // api target 1
    
                androidx.databinding.adapters.TextViewBindingAdapter.setText(this.text1, personUserNameGet);
            }
            if ((dirtyFlags & 0x4L) != 0) {
                // api target 1
    
                androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.text1, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, text1androidTextAttrChanged);
            }
        }
    

    可以看到,最终调用executeBindings()方法。实际上,View和BaseObservable数据的相互绑定就在这个方法里面。

    • View变化,通知BaseObservable数据刷新
      看源码倒数第三行,通过setTextWatcher()方法对view进行监听,看下text1androidTextAttrChanged是啥:
    // variables
        // values
        // listeners
        // Inverse Binding Event Handlers
        private androidx.databinding.InverseBindingListener text1androidTextAttrChanged = new androidx.databinding.InverseBindingListener() {
            @Override
            public void onChange() {
                // Inverse of person.userName.get()
                //         is person.userName.set((java.lang.String) callbackArg_0)
                java.lang.String callbackArg_0 = androidx.databinding.adapters.TextViewBindingAdapter.getTextString(text1);
                // localize variables for thread safety
                // person
                com.example.databingtest2.Person person = mPerson;
                // person.userName
                androidx.databinding.ObservableField<java.lang.String> personUserName = null;
                // person.userName.get()
                java.lang.String personUserNameGet = null;
                // person != null
                boolean personJavaLangObjectNull = false;
                // person.userName != null
                boolean personUserNameJavaLangObjectNull = false;
    
    
    
                personJavaLangObjectNull = (person) != (null);
                if (personJavaLangObjectNull) {
    
    
                    personUserName = person.getUserName();
    
                    personUserNameJavaLangObjectNull = (personUserName) != (null);
                    if (personUserNameJavaLangObjectNull) {
    
    
    
    
                        personUserName.set(((java.lang.String) (callbackArg_0)));
                    }
                }
            }
        };
    
    

    在InverseBindingListener中监听,当View的text改变时,刷新BaseObservable数据的值。
    那么BaseObservable数据的值改变,怎么监听呢?我们先看下BaseObservable的源码:

    public class BaseObservable implements Observable {
        private transient PropertyChangeRegistry mCallbacks;
    
        public BaseObservable() {
        }
    
        @Override
        public void addOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
            synchronized (this) {
                if (mCallbacks == null) {
                    mCallbacks = new PropertyChangeRegistry();
                }
            }
            mCallbacks.add(callback);
        }
    
        @Override
        public void removeOnPropertyChangedCallback(@NonNull OnPropertyChangedCallback callback) {
            synchronized (this) {
                if (mCallbacks == null) {
                    return;
                }
            }
            mCallbacks.remove(callback);
        }
    
        /**
         * Notifies listeners that all properties of this instance have changed.
         */
        public void notifyChange() {
            synchronized (this) {
                if (mCallbacks == null) {
                    return;
                }
            }
            mCallbacks.notifyCallbacks(this, 0, null);
        }
    
        /**
         * Notifies listeners that a specific property has changed. The getter for the property
         * that changes should be marked with {@link Bindable} to generate a field in
         * <code>BR</code> to be used as <code>fieldId</code>.
         *
         * @param fieldId The generated BR id for the Bindable field.
         */
        public void notifyPropertyChanged(int fieldId) {
            synchronized (this) {
                if (mCallbacks == null) {
                    return;
                }
            }
            mCallbacks.notifyCallbacks(this, fieldId, null);
        }
    }
    

    继承Observable,我们看下Observable的源码:

    public interface Observable {
    
        /**
         * Adds a callback to listen for changes to the Observable.
         * @param callback The callback to start listening.
         */
        void addOnPropertyChangedCallback(OnPropertyChangedCallback callback);
    
        /**
         * Removes a callback from those listening for changes.
         * @param callback The callback that should stop listening.
         */
        void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback);
    
        /**
         * The callback that is called by Observable when an observable property has changed.
         */
        abstract class OnPropertyChangedCallback {
    
            /**
             * Called by an Observable whenever an observable property changes.
             * @param sender The Observable that is changing.
             * @param propertyId The BR identifier of the property that has changed. The getter
             *                   for this property should be annotated with {@link Bindable}.
             */
            public abstract void onPropertyChanged(Observable sender, int propertyId);
        }
    }
    

    可以看到Observable有回调接口OnPropertyChangedCallback,所以在DataBinding里面肯定是有对BaseObservable数据的监听设置的。那么它在哪儿呢?
    在上面的executeBindings()方法内部有这样一个方法:updateRegistration(),其实就是在这里绑定,我们看其源码:

      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;
        }
    
    /**
         * @hide
         */
        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);
        }
    

    最终到了WeakListener中,我们看下WeakListener是什么?

    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;
            }
        }
    
        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);
            }
        }
    
        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 setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            }
    
            @Override
            public WeakListener<ObservableList> getListener() {
                return mListener;
            }
    
            @Override
            public void addListener(ObservableList target) {
                target.addOnListChangedCallback(this);
            }
    
            @Override
            public void removeListener(ObservableList target) {
                target.removeOnListChangedCallback(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 setLifecycleOwner(LifecycleOwner lifecycleOwner) {
            }
    
            @Override
            public WeakListener<ObservableMap> getListener() {
                return mListener;
            }
    
            @Override
            public void addListener(ObservableMap target) {
                target.addOnMapChangedCallback(this);
            }
    
            @Override
            public void removeListener(ObservableMap target) {
                target.removeOnMapChangedCallback(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 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
            public WeakListener<LiveData<?>> getListener() {
                return mListener;
            }
    
            @Override
            public void addListener(LiveData<?> target) {
                if (mLifecycleOwner != null) {
                    target.observe(mLifecycleOwner, this);
                }
            }
    
            @Override
            public void removeListener(LiveData<?> target) {
                target.removeObserver(this);
            }
    
            @Override
            public void onChanged(@Nullable Object o) {
                ViewDataBinding binder = mListener.getBinder();
                if (binder != null) {
                    binder.handleFieldChange(mListener.mLocalFieldId, mListener.getTarget(), 0);
                }
            }
        }
    
        private interface CreateWeakListener {
            WeakListener create(ViewDataBinding viewDataBinding, int localFieldId);
        }
    

    WeakListener有好几种实现,比如LiveDataListener、WeakMapListener、WeakListListener、WeakPropertyListener、WeakListener,我们通过源码知道,WeakListener通过CREATE_PROPERTY_LISTENER创建的,我们看下CREATE_PROPERTY_LISTENER是啥:

     /**
         * Method object extracted out to attach a listener to a bound Observable object.
         */
        private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
            @Override
            public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
                return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
            }
        };
    
        /**
         * Method object extracted out to attach a listener to a bound ObservableList object.
         */
        private static final CreateWeakListener CREATE_LIST_LISTENER = new CreateWeakListener() {
            @Override
            public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
                return new WeakListListener(viewDataBinding, localFieldId).getListener();
            }
        };
    
        /**
         * Method object extracted out to attach a listener to a bound ObservableMap object.
         */
        private static final CreateWeakListener CREATE_MAP_LISTENER = new CreateWeakListener() {
            @Override
            public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
                return new WeakMapListener(viewDataBinding, localFieldId).getListener();
            }
        };
    
        /**
         * Method object extracted out to attach a listener to a bound LiveData object.
         */
        private static final CreateWeakListener CREATE_LIVE_DATA_LISTENER = new CreateWeakListener() {
            @Override
            public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
                return new LiveDataListener(viewDataBinding, localFieldId).getListener();
            }
        };
    

    CREATE_PROPERTY_LISTENER内部创建了WeakPropertyListener,我们定位到WeakPropertyListener:

    c 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);
            }
        }
    
    

    这个就很明显了,target.addOnPropertyChangedCallback设置监听,然后在onPropertyChanged方法内部调用handleFieldChange()方法,我们看下handleFieldChange源码:

    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();
            }
        }
    

    看到requestRebind()方法,继续找下去发现最终还是调用了executeBindings()刷新View的值。
    这样,View和BaseObservable数据的相互绑定就完成了。

    3.BindingAdapter的原理

    在DataBinding中,我们知道在xml中可以直接自定义绑定数据,那么它是怎么实现的呢?
    其实很简单,我们还是看下executeBindings()方法:

    @Override
        protected void executeBindings() {
            long dirtyFlags = 0;
            synchronized(this) {
                dirtyFlags = mDirtyFlags;
                mDirtyFlags = 0;
            }
            com.example.databingtest2.Person person = mPerson;
            int personColor = 0;
            androidx.databinding.ObservableField<java.lang.String> personUserName = null;
            java.lang.String personUserNameGet = null;
    
            if ((dirtyFlags & 0x7L) != 0) {
    
    
                if ((dirtyFlags & 0x6L) != 0) {
    
                        if (person != null) {
                            // read person.color
                            personColor = person.getColor();
                        }
                }
    
                    if (person != null) {
                        // read person.userName
                        personUserName = person.getUserName();
                    }
                    updateRegistration(0, personUserName);
    
    
                    if (personUserName != null) {
                        // read person.userName.get()
                        personUserNameGet = personUserName.get();
                    }
            }
            // batch finished
            if ((dirtyFlags & 0x6L) != 0) {
                // api target 1
    
                com.example.databingtest2.DataBindingAdapterExtKt.setTextViewColor(this.text1, personColor); // ---->①
            }
            if ((dirtyFlags & 0x7L) != 0) {
                // api target 1
    
                androidx.databinding.adapters.TextViewBindingAdapter.setText(this.text1, personUserNameGet);// ----> ②
            }
            if ((dirtyFlags & 0x4L) != 0) {
                // api target 1
    
                androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.text1, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, text1androidTextAttrChanged);
            }
        }
    

    在代码中①②中,我们看到对View设置属性时是直接调用了相对应的方法。其实DataBinding有很多默认实现,我们看下:


    image.png

    它们里面是静态方法,可以直接调用。

    上面介绍了DataBinding的原理和作用机制,如果大家有什么问题,欢迎提出讨论!

    相关文章

      网友评论

          本文标题:DataBinding浅析

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