问题
Updating ObservableField
inside onActivityResult(..)
of activity
but not reflecting that value to XML
. If I call executePendingBindings() it will work. But the issue is, there are a lot of ObservableField
and for every variable, I need to call executePendingBindings()
.
Anyone knows how to solve this issue ?
回答1:
In ViewDataBinding.java
file, there is one method for requesting rebind
protected void requestRebind() {
if (mContainingBinding != null) {
mContainingBinding.requestRebind();
} else {
synchronized (this) {
if (mPendingRebind) {
return;
}
mPendingRebind = true;
}
if (mLifecycleOwner != null) {
Lifecycle.State state = mLifecycleOwner.getLifecycle().getCurrentState();
if (!state.isAtLeast(Lifecycle.State.STARTED)) {
return; // wait until lifecycle owner is started
}
}
if (USE_CHOREOGRAPHER) {
mChoreographer.postFrameCallback(mFrameCallback);
} else {
mUIThreadHandler.post(mRebindRunnable);
}
}
}
When control enters that method mPendingRebind
will be false and it will be made true by this method. mChoreographer.postFrameCallback(mFrameCallback);
will make that variable again to false so that other bindings will update the view.
The issue was !state.isAtLeast(Lifecycle.State.STARTED)
condition. Since ObservableField is updated from onActivityResult(..)
, the current state will be Lifecycle.State.CREATED
So that condition will fail and return that method without calling mChoreographer.postFrameCallback(mFrameCallback);
and mPendingRebind
will be true. So remaining bindings will not update.
So the solution was to call SingleLiveEvent
and observe that variable. When that callback is received, we have to update ObservableField()
For eg :
val updateObserver = SingleLiveEvent<Unit>()
Then observe for that event
updateObserver.observe(this, Observer {
//update ObservableField
})
Call that event from onActivityResult
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == 111 && resultCode == Activity.RESULT_OK) {
updateObserver.call()
}
}
回答2:
If you don't want to create a SingleLiveEvent
and prefer to keep your callback code in onActivityResult
, and you have a base activity where all activities extend from, you can add a scheduleUpdateAfterOnActivityResult
method to the base activity:
// When onActivityResult is run, the activity is still in Lifecycle.State.CREATED and
// bindings will not fire. Schedule the update by creating a new MutableLiveData,
// which will fire observers when activity lifecycle is active.
// See also https://stackoverflow.com/questions/53104670/data-binding-xml-not-updating-after-onactivityresult/53107092
public <T> void scheduleUpdateAfterOnActivityResult(T data, Observer<T> observer) {
final MutableLiveData<T> liveData = new MutableLiveData<>();
liveData.observe(this, new Observer<T>() {
@Override
public void onChanged(@Nullable final T v) {
observer.onChanged(v);
liveData.removeObserver(this);
}
});
liveData.postValue(data);
}
then in
onActivityResult
call scheduleUpdateAfterOnActivityResult()
:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_CODE_XXXX && data != null) {
scheduleUpdateAfterOnActivityResult(data, bundle -> {
// do something
}
}
super.onActivityResult(requestCode, resultCode, data);
}
来源:https://stackoverflow.com/questions/53104670/data-binding-xml-not-updating-after-onactivityresult