jetpack-LiveData实现双向绑定原理
重要的行代码
mDbActivityBinding.lifecycleOwner = this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mDbActivityBinding = DataBindingUtil.setContentView(this, R.layout.db_activity)
mDbActivityBinding.mdbViewModel =
ViewModelProviders.of(this).get(DBViewModel::class.java)
mDbActivityBinding.lifecycleOwner = this
@OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onStart() {
ViewDataBinding dataBinding = mBinding.get();
if (dataBinding != null) {
dataBinding.executePendingBindings();
}
}
ViewDataBinding.executeBindingsInternal
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;
}
executeBindings(),这里有注册监听(如果没注册)和把数据绑定到TextView
@Override
protected void executeBindings() {
long dirtyFlags = 0;
synchronized(this) {
dirtyFlags = mDirtyFlags;
mDirtyFlags = 0;
}
java.lang.String mDBViewModelUserLastName = null;
com.seekting.demo2019.jetpack.DBViewModel mDBViewModel = mMDBViewModel;
com.seekting.demo2019.jetpack.User mDBViewModelUserGetValue = null;
java.lang.String mDBViewModelUserFirstName = null;
java.lang.String mDBViewModelPwd = null;
androidx.lifecycle.MutableLiveData<com.seekting.demo2019.jetpack.User> mDBViewModelUser = null;
androidx.databinding.ObservableField<java.lang.String> mDBViewModelUserFullName = null;
java.lang.String mDBViewModelUserFullNameGet = null;
if ((dirtyFlags & 0x17L) != 0) {
if ((dirtyFlags & 0x14L) != 0) {
if (mDBViewModel != null) {
// read mDBViewModel.pwd
mDBViewModelPwd = mDBViewModel.getPwd();
}
}
if (mDBViewModel != null) {
// read mDBViewModel.user
mDBViewModelUser = mDBViewModel.getUser();
}
updateLiveDataRegistration(0, mDBViewModelUser);
if (mDBViewModelUser != null) {
// read mDBViewModel.user.getValue()
mDBViewModelUserGetValue = mDBViewModelUser.getValue();
}
if ((dirtyFlags & 0x15L) != 0) {
if (mDBViewModelUserGetValue != null) {
// read mDBViewModel.user.getValue().lastName
mDBViewModelUserLastName = mDBViewModelUserGetValue.getLastName();
// read mDBViewModel.user.getValue().firstName
mDBViewModelUserFirstName = mDBViewModelUserGetValue.getFirstName();
}
}
if (mDBViewModelUserGetValue != null) {
// read mDBViewModel.user.getValue().fullName
mDBViewModelUserFullName = mDBViewModelUserGetValue.getFullName();
}
updateRegistration(1, mDBViewModelUserFullName);
if (mDBViewModelUserFullName != null) {
// read mDBViewModel.user.getValue().fullName.get()
mDBViewModelUserFullNameGet = mDBViewModelUserFullName.get();
}
}
// batch finished
if ((dirtyFlags & 0x15L) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView1, mDBViewModelUserFirstName);
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView2, mDBViewModelUserLastName);
}
if ((dirtyFlags & 0x10L) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.mboundView1, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, mboundView1androidTextAttrChanged);
androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.mboundView2, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, mboundView2androidTextAttrChanged);
androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.mboundView3, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, mboundView3androidTextAttrChanged);
androidx.databinding.adapters.TextViewBindingAdapter.setTextWatcher(this.mboundView4, (androidx.databinding.adapters.TextViewBindingAdapter.BeforeTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.OnTextChanged)null, (androidx.databinding.adapters.TextViewBindingAdapter.AfterTextChanged)null, mboundView4androidTextAttrChanged);
this.mboundView5.setOnClickListener(mCallback1);
}
if ((dirtyFlags & 0x17L) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView3, mDBViewModelUserFullNameGet);
}
if ((dirtyFlags & 0x14L) != 0) {
// api target 1
androidx.databinding.adapters.TextViewBindingAdapter.setText(this.mboundView4, mDBViewModelPwd);
}
}
updateLiveDataRegistration会调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(observable)
第i个成员变量监听了livedata的变化
public void setTarget(T object) {
unregister();
mTarget = object;
if (mTarget != null) {
"mObservable就是LiveData"
mObservable.addListener(mTarget);
}
}
当setValue被调用
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
void dispatchingValue(@Nullable ObserverWrapper initiator) {
if (mDispatchingValue) {
mDispatchInvalidated = true;
return;
}
mDispatchingValue = true;
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
mDispatchingValue = false;
}
considerNotify
@SuppressWarnings("unchecked")
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
@Override
public void onChanged(@Nullable Object o) {
ViewDataBinding binder = mListener.getBinder();
if (binder != null) {
binder.handleFieldChange(mListener.mLocalFieldId, mListener.getTarget(), 0);
}
}
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();
}
}
请求重新绑定
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
}
}
synchronized (this) {
if (mPendingRebind) {
return;
}
mPendingRebind = true;
}
if (USE_CHOREOGRAPHER) {
mChoreographer.postFrameCallback(mFrameCallback);
} else {
mUIThreadHandler.post(mRebindRunnable);
}
}
}
@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();
}
又回到了executePendingBindings,它负责注册监听(如果没监听 )和数据绑定到TextView