A brief explanation of commitAllowingStateLoss

Overview

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.

Details

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.

Considering the implementation of Activity

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.

At the end

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

A brief explanation of commitAllowingStateLoss
A brief description of JAVA dependencies
A brief summary of DI and DI containers
Let's create a TODO application in Java 1 Brief explanation of MVC
Rails: A brief summary of find, find_by, where
A brief summary of Rails association options (foreign_key, primary_key)
A rough explanation of how Java-based web applications work
A brief explanation of a maze game made in Java for a cousin of an elementary school student
A quick explanation of the five types of static in Java
Creating a batch of Liferay
Explanation of the FizzBuzz problem
Explanation of Ruby on rails for beginners ③ ~ Creating a database ~
Think of a Java update strategy
[Docker Network Chapter 1] Explanation of Docker Networking
A list of rawValues for UITextContentType.
A memorandum of the FizzBuzz problem
A memorandum of personal phpenv install
Explanation about Array object of Ruby
History of a certain in-house SE
A little understanding of lambda expressions