Databinding

类设计

在liveData数据变化回调onChanged之后,触发requestRebind,在executeBindings时根据dirtyFlags通过BindingAdapter方法刷新View属性

基于androidx.databinding:databinding-runtime:4.0.1

DataBindingUtil

private static DataBinderMapper sMapper = new DataBinderMapperImpl();
private static DataBindingComponent sDefaultComponent = null;

setContentView

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

bindToAddedViews

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

bind

static <T extends ViewDataBinding> T bind(DataBindingComponent bindingComponent, View[] roots,
        int layoutId) {
    return (T) sMapper.getDataBinder(bindingComponent, roots, layoutId);
}

sMapper

MergedDataBinderMapper

public class MergedDataBinderMapper extends DataBinderMapper {
  private List<DataBinderMapper> mMappers = new CopyOnWriteArrayList<>();
}

getDataBinder

@Override
public ViewDataBinding getDataBinder(DataBindingComponent bindingComponent, View view,
        int layoutId) {
    for(DataBinderMapper mapper : mMappers) {
        ViewDataBinding result = mapper.getDataBinder(bindingComponent, view, layoutId);
        if (result != null) {
            return result;
        }
    }
    return null;
}

androidx.databinding.DataBinderMapperImpl

public class DataBinderMapperImpl extends MergedDataBinderMapper {
  DataBinderMapperImpl() {
    addMapper(new com.example.myapplication.DataBinderMapperImpl());
  }
}

com.example.myapplication.DataBinderMapperImpl

getDataBinder

@Override
public ViewDataBinding getDataBinder(DataBindingComponent component, View view, int layoutId) {
  int localizedLayoutId = INTERNAL_LAYOUT_ID_LOOKUP.get(layoutId);
    final Object tag = view.getTag();
    switch(localizedLayoutId) {
      case  LAYOUT_ACTIVITYLOGIN: {
        if ("layout/activity_login_0".equals(tag)) {
          return new ActivityLoginBindingImpl(component, view);
        }
      }
    }
}

ViewDatabinding

mFrameCallback

private final Choreographer.FrameCallback mFrameCallback;

CREATE_LIVE_DATA_LISTENER

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

livedatalistener

constructor

protected ViewDataBinding(DataBindingComponent bindingComponent, View root, int localFieldCount) {
    mBindingComponent = bindingComponent;
    mLocalFieldObservers = new WeakListener[localFieldCount];
    this.mRoot = root;
        mChoreographer = Choreographer.getInstance();
        mFrameCallback = new Choreographer.FrameCallback() {
            @Override
            public void doFrame(long frameTimeNanos) {
                mRebindRunnable.run();
            }
        };
}

mrebindrunnable

setLifecycleOwner

public void setLifecycleOwner(@Nullable LifecycleOwner lifecycleOwner) {
    ......
    mLifecycleOwner = lifecycleOwner;
    if (lifecycleOwner != null) {
        if (mOnStartListener == null) {
            mOnStartListener = new OnStartListener(this);
        }
        lifecycleOwner.getLifecycle().addObserver(mOnStartListener);
    }
    for (WeakListener<?> weakListener : mLocalFieldObservers) {
        if (weakListener != null) {
            weakListener.setLifecycleOwner(lifecycleOwner);
        }
    }
}

OnStartListener

static class OnStartListener implements LifecycleObserver {
    final WeakReference<ViewDataBinding> mBinding;
    private OnStartListener(ViewDataBinding binding) {
        mBinding = new WeakReference<>(binding);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    public void onStart() {
        ViewDataBinding dataBinding = mBinding.get();
        if (dataBinding != null) {
            dataBinding.executePendingBindings();
        }
    }
}

executependingbindings

requestRebind

protected void requestRebind() {
    if (mContainingBinding != null) {
        mContainingBinding.requestRebind();
    } else {
        final LifecycleOwner owner = this.mLifecycleOwner;
        if (owner != null) {
            Lifecycle.State state = owner.getLifecycle().getCurrentState();
            if (!state.isAtLeast(Lifecycle.State.STARTED)) {
                return; // wait until lifecycle owner is started
            }
        }
        mChoreographer.postFrameCallback(mFrameCallback);
    }
}

mFrameCallback

mRebindRunnable

private final Runnable mRebindRunnable = new Runnable() {
    @Override
    public void run() {
        processReferenceQueue();
        executePendingBindings();
    }
};

executePendingBindings

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

executeBindingsInternal

private void executeBindingsInternal() {
     .......
     executeBindings();
     ......
}

executebindings

updateLiveDataRegistration

protected boolean updateLiveDataRegistration(int localFieldId, LiveData<?> observable) {
    mInLiveDataRegisterObserver = true;
    try {
        return updateRegistration(localFieldId, observable, CREATE_LIVE_DATA_LISTENER);
    } finally {
        mInLiveDataRegisterObserver = false;
    }
}

updateRegistration

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

registerTo

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

listener

settarget

handleFieldChange

private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
    boolean result = onFieldChange(mLocalFieldId, object, fieldId);
    if (result) {
        requestRebind();
    }
}

onfieldchange

requestrebind

LiveDataListener

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

getListener

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

addListener

@Override
public void addListener(LiveData<?> target) {
    if (mLifecycleOwner != null) {
        target.observe(mLifecycleOwner, this);
    }
}

onChanged

@Override
public void onChanged(@Nullable Object o) {
    ViewDataBinding binder = mListener.getBinder();
    if (binder != null) {
        binder.handleFieldChange(mListener.mLocalFieldId, mListener.getTarget(), 0);
    }
}

handlefieldchange

WeakListener

private final ObservableReference<T> mObservable;

setTarget

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

addlistener

ActivityLoginBindingImpl

private ActivityLoginBindingImpl(androidx.databinding.DataBindingComponent bindingComponent, View root, Object[] bindings) {
    super(bindingComponent, root, 3
        , (android.widget.Button) bindings[3]
        , (android.widget.EditText) bindings[2]
        , (com.example.myapplication.arch.login.CustomTextView) bindings[4]
        , (android.widget.EditText) bindings[1]
        );
    this.login.setTag(null);
    this.mboundView0 = (androidx.constraintlayout.widget.ConstraintLayout) bindings[0];
    this.mboundView0.setTag(null);
    this.password.setTag(null);
    this.uid.setTag(null);
    this.userName.setTag(null);
    setRootTag(root);
    // listeners
    mCallback1 = new com.example.myapplication.generated.callback.OnClickListener(this, 1);
    invalidateAll();
}

invalidateAll

public void invalidateAll() {
    synchronized(this) {
         mDirtyFlags = 0x10L;
    }
    requestRebind();
}

requestrebind

setVm

    public void setVm(@Nullable com.example.myapplication.arch.login.LoginViewModel Vm) {
        this.mVm = Vm;
        synchronized(this) {
            mDirtyFlags |= 0x8L;
        }
        notifyPropertyChanged(BR.vm);
        super.requestRebind();
    }

onFieldChange

@Override
protected boolean onFieldChange(int localFieldId, Object object, int fieldId) {
    switch (localFieldId) {
        case 0 :
            return onChangeVmUserNameLiveData((androidx.lifecycle.MutableLiveData<java.lang.String>) object, fieldId);
        case 1 :
            return onChangeVmUidLiveData((androidx.lifecycle.MutableLiveData<java.lang.String>) object, fieldId);
        case 2 :
            return onChangeVmPasswordLiveData((androidx.lifecycle.MutableLiveData<java.lang.String>) object, fieldId);
    }
    return false;
}

onChangeVmUidLiveData

private boolean onChangeVmUidLiveData(androidx.lifecycle.MutableLiveData<java.lang.String> VmUidLiveData, int fieldId) {
    if (fieldId == BR._all) {
        synchronized(this) {
                mDirtyFlags |= 0x2L;
        }
        return true;
    }
    return false;
}

executeBindings

@Override
protected void executeBindings() {
    long dirtyFlags = 0;
    synchronized(this) {
        dirtyFlags = mDirtyFlags;
        mDirtyFlags = 0;
    }
    java.lang.String vmUserNameLiveDataGetValue = null;
    androidx.lifecycle.MutableLiveData<java.lang.String> vmUserNameLiveData = null;
    androidx.lifecycle.MutableLiveData<java.lang.String> vmUidLiveData = null;
    com.example.myapplication.arch.login.LoginViewModel vm = mVm;
    java.lang.String vmUidLiveDataGetValue = null;
    java.lang.String vmPasswordLiveDataGetValue = null;
    androidx.lifecycle.MutableLiveData<java.lang.String> vmPasswordLiveData = null;

  
    ......
         if ((dirtyFlags & 0x1aL) != 0) {
                    if (vm != null) {
                        // read vm.uidLiveData
                        vmUidLiveData = vm.getUidLiveData();
                    }
                    updateLiveDataRegistration(1, vmUidLiveData);


                    if (vmUidLiveData != null) {
                        // read vm.uidLiveData.getValue()
                        vmUidLiveDataGetValue = vmUidLiveData.getValue();
                    }
           
                    //从LiveData的T中提取嵌套子数据data时,会生成如下的提取field代码
                    //xml中绑定的数据为: @{vm.uidLiveData.data}
                    if (vmUidLiveDataGetValue != null) {
                        // read vm.uidLiveData.getValue().data
                        vmUidLiveDataData = vmUidLiveDataGetValue.getData();
                    }
         }
        if ((dirtyFlags & 0x1aL) != 0) {
            // api target 1
            //从LiveData的T中提取嵌套子数据data时, 会用vmUidLiveDataData替代vmUidLiveDataGetValue
            androidx.databinding.adapters.TextViewBindingAdapter.setText(this.uid, vmUidLiveDataGetValue);
            com.example.myapplication.arch.login.CustomTextView.changeBgIfLong(this.uid, vmUidLiveDataGetValue);
        }
}

updatelivedataregistration

参考

RecyclerView

https://developer.android.google.cn/guide/topics/ui/layout/recyclerview

Android Data Binding: RecyclerView

Refactoring RecyclerView adapter to data binding