Resolving IllegalStateException: “Cannot Perform This Action After onSaveInstanceState” with ViewPager

Resolving IllegalStateException: "Cannot Perform This Action After onSaveInstanceState" with ViewPager

6 June 2024 Stephan Petzl Leave a comment Tech-Help

Encountering an IllegalStateException with the message “Cannot perform this action after onSaveInstanceState” can be challenging, especially when dealing with ViewPager and FragmentManager. This article will guide you through understanding the issue and implementing effective solutions.

Understanding the Issue

The IllegalStateException typically occurs when a fragment transaction is attempted after the activity state has already been saved. This usually happens if user actions like pressing the home button or rotating the device trigger the onSaveInstanceState method, thus making it unsafe to commit fragment transactions.

Common Scenarios and Solutions

1. Avoiding the Call to super.onSaveInstanceState

One of the most straightforward solutions involves overriding the onSaveInstanceState method without calling its superclass method. This approach is useful but should be applied cautiously as it may prevent the state from being saved correctly.

@Override
protected void onSaveInstanceState(Bundle outState) {
    // No call to super(). Bug on API Level > 11.
}

2. Using commitAllowingStateLoss

Another solution is to use commitAllowingStateLoss instead of commit for fragment transactions. This method allows the transaction to be committed even after the state has been saved, thus preventing the exception.

FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.commitAllowingStateLoss();

3. Checking Fragment State Before Transaction

Before performing a fragment transaction, check if the state has been saved to avoid committing when it is unsafe.

if (!isStateSaved()) {
    fragmentManager.popBackStackImmediate();
}

4. Lifecycle-Aware Components

Utilize Android’s Lifecycle components to manage fragment transactions more effectively. By checking the lifecycle state, you can ensure that transactions are only performed when it is safe to do so.

if (lifecycle.currentState.isAtLeast(Lifecycle.State.RESUMED)) {
    showFragment(frag);
}

Implementing a Robust Solution

Combining these approaches can help create a more robust solution. For instance, maintaining a pending transaction list and committing transactions only when the activity is in the appropriate state can prevent the exception while ensuring UI consistency.

class FragmentDispatcher(_host: FragmentActivity) : LifecycleObserver {
    private val hostActivity: FragmentActivity? = _host
    private val lifecycle: Lifecycle? = _host.lifecycle
    private val pendingList = mutableListOf()

    @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
    fun resume() {
        if (pendingList.isNotEmpty()) {
            showFragment(pendingList.last())
        }
    }

    fun dispatchFragment(frag: BaseFragment) {
        if (lifecycle?.currentState?.isAtLeast(Lifecycle.State.RESUMED) == true) {
            showFragment(frag)
        } else {
            pendingList.clear()
            pendingList.add(frag)
        }
    }

    private fun showFragment(frag: BaseFragment) {
        hostActivity?.let {
            val transaction = it.supportFragmentManager.beginTransaction()
            transaction.replace(R.id.container, frag)
            transaction.commit()
        }
    }
}

Enhancing Your Workflow with Repeato

While managing fragment transactions and lifecycle states can be complex, tools like Repeato can significantly simplify your development and testing process. Repeato is a no-code test automation tool for iOS and Android, leveraging computer vision and AI to create, run, and maintain automated tests rapidly.

Using Repeato, mobile developers can focus on building great products without worrying about the intricacies of test automation. It also empowers non-technical colleagues or QA teams to handle test automation, ensuring a more efficient workflow and robust application quality.

For more information on how Repeato can assist in your development process, visit our documentation or contact us.

Like this article? there’s more where that came from!