Checking if state is saved before committing a FragmentTransaction

hwrdprkns picture hwrdprkns · Feb 13, 2013 · Viewed 21.9k times · Source

I sometimes see the following stacktrace for a commit that can happen when the user isn't looking at the activity (after state's been saved):

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
    at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1327)
    at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1338)
    at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
    at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)

Looking at the Android source, this makes total sense:

private void checkStateLoss() {
        if (mStateSaved) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
        if (mNoTransactionsBecause != null) {
            throw new IllegalStateException(
                    "Can not perform this action inside of " + mNoTransactionsBecause);
        }
 }

Now, I wonder if there is any way (besides storing a class variable in on(Save/Restore)InstanceState) to check if a fragment is going to be committed in an undesirable state, this way I can store the transaction for later and make the commit at the appropriate time.

Answer

azizbekian picture azizbekian · May 19, 2017

Starting from support library version 26.0.0 Beta 1 a new API is available in FragmentManager and Fragment classes:

FragmentManager and Fragment have an isStateSaved() method to allow querying whether or not a transaction will be allowed without state loss. This is especially useful to check when handling an onClick() event before executing any transaction.

From docs of android.support.v4.app.FragmentManager#isStateSaved():

Returns true if the FragmentManager's state has already been saved by its host. Any operations that would change saved state should not be performed if this method returns true. For example, any popBackStack() method, such as popBackStackImmediate() or any FragmentTransaction using commit() instead of commitAllowingStateLoss() will change the state and will result in an error.

This API will ship with framework's android.app.FragmentManager starting from Android O.