When committing an arbitrary Fragment with FragmentTransaction, there is a case where FragmentTransaction # commitAllowingStateLoss is used to avoid IllegalStateException, but I will briefly explain what happens when commitAllowingStateLoss is used.
commitAllowingStateLoss javadoc https://developer.android.com/reference/android/app/FragmentTransaction.html#commitAllowingStateLoss()
Like commit() but allows the commit to be executed after an activity's state is saved. This is dangerous because the commit can be lost if the activity needs to later be restored from its state, so this should only be used for cases where it is okay for the UI state to change unexpectedly on the user.
The point is "This is dangerous because the commit can be lost if the activity needs to later be restored from its state", literally translated by google teacher "This is a commit if you need to restore the activity from the state later" It is dangerous because it can be lost. " I don't understand. .. ..
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
If you don't commitAllowingStateLoss, you can't commit after onSaveInstanceState with IllegalStateException! Get angry. Let's take a look at the source of Activity # onSaveInstanceState to understand the javadoc earlier.
Activity.java
protected void onSaveInstanceState(Bundle outState) {
outState.putBundle(WINDOW_HIERARCHY_TAG, mWindow.saveHierarchyState());
outState.putInt(LAST_AUTOFILL_ID, mLastAutofillId);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
if (mAutoFillResetNeeded) {
outState.putBoolean(AUTOFILL_RESET_NEEDED, true);
getAutofillManager().onSaveInstanceState(outState);
}
getApplication().dispatchActivitySaveInstanceState(this, outState);
}
Parcelable p = mFragments.saveAllState ();
and ʻoutState.putParcelable (FRAGMENTS_TAG, p);
It seems that the Fragment object is completely saved with `.
Where will the saved Fragment be restored? ..
MainActivity.java
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (getApplicationInfo().targetSdkVersion > O && mActivityInfo.isFixedOrientation()) {
final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
ta.recycle();
if (isTranslucentOrFloating) {
throw new IllegalStateException(
"Only fullscreen opaque activities can request orientation");
}
}
if (mLastNonConfigurationInstances != null) {
mFragments.restoreLoaderNonConfig(mLastNonConfigurationInstances.loaders);
}
if (mActivityInfo.parentActivityName != null) {
if (mActionBar == null) {
mEnableDefaultActionBarUp = true;
} else {
mActionBar.setDefaultDisplayHomeAsUpEnabled(true);
}
}
if (savedInstanceState != null) {
mAutoFillResetNeeded = savedInstanceState.getBoolean(AUTOFILL_RESET_NEEDED, false);
mLastAutofillId = savedInstanceState.getInt(LAST_AUTOFILL_ID,
View.LAST_APP_AUTOFILL_ID);
if (mAutoFillResetNeeded) {
getAutofillManager().onCreate(savedInstanceState);
}
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, mLastNonConfigurationInstances != null
? mLastNonConfigurationInstances.fragments : null);
}
mFragments.dispatchCreate();
getApplication().dispatchActivityCreated(this, savedInstanceState);
if (mVoiceInteractor != null) {
mVoiceInteractor.attachActivity(this);
}
mCalled = true;
}
In onCreate, get the Fragment saved with Parcelable p = savedInstanceState.getParcelable (FRAGMENTS_TAG);
and restore it with mFragments.restoreAllState (p, mLastNonConfigurationInstances! = Null? mLastNonConfigurationInstances.fragments: null);
.
It seems that the point is the implementation that saves the Fragment completely with onSaveInstanceState and restores the Fragment completely saved with onCreate.
The meaning of "commit is lost when activity needs to be restored from state" in commitAllowingStateLoss is that even if you commit Fragment for the purpose you saw in commitAllowingStateLoss after onSaveInstanceState, the Fragment has already been saved in onSaveInstanceState. , Changes between onSaveInstanceState and commitAllowingStateLoss are not retained. I understand that it means that the state cannot be restored when the activity is regenerated.
After all, you should use commitAllowingStateLoss only when you don't need to maintain the state.
When I first encountered commitAllowingStateLoss, I was wondering what would be lost and made a PG to check the operation, and I self-solved that I was losing, but this time the code was lost. Remains unable to explain exactly what is lost. .. I'm sorry. .. ..
Recommended Posts