First of all, I've read dozens of SO questions and read excellent post by Alex Lockwood about the IllegalStateException
problems connected with fragment transactions: https://www.androiddesignpatterns.com/2013/08/fragment-transaction-commit-state-loss.html - tl;dr I've done my homework
But what I didn't find anywhere is the IllegalStateException
problem when the screen goes off and we are trying to commit fragment transaction - show DialogFragment
in my case.
What is exactly happening in my app is reacting to other activity result and later on showing a DialogFragment
. As suggested by many SO users, I'm not showing dialog from onActivityResult
but from onPostResume
(I've tried also with onResumeFragments
) Simplified code looks like this
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
Timber.i("${this::class.java.simpleName} onActivityResult")
activityResult = ActivityResult(this::class, requestCode, resultCode, data)
}
override fun onPostResume() {
super.onPostResume()
Timber.i("${this::class.java.simpleName} onPostResume")
activityResult?.let { ActivityResultRepository.resultsSubject.onNext(it) }
}
override fun onResumeFragments() {
super.onResumeFragments()
Timber.i("${this::class.java.simpleName} onResumeFragments")
}
I couldn't reproduce exception on my device (Mate 20 pro) or on emulator but I'm receiving crash reports from users of my app (0.5% users affected)
My assumption is, my app is trying to show a dialog after screen goes off. Screen going off is an arbitrary event that causes onSaveInstanceState
method to be called and it can be called right before my onPostResume
method. However this is only my assumption!, maybe there is another cause of the exception
Has anyone experienced similar problems and manage to handle them? I know I can use commitAllowingStateLoss
but firstly - show
method of DialogFragment
doesn't allow to do that, would have to show dialog manually by using FragmentManager
(don't know if there are any implications), secondly commitAllowingStateLoss
is generally a bad thing to do
I'm adding crash report although everyone saw it already somewhere :)
Caused by java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:2053)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:2079)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:678)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:632)
at android.support.v4.app.DialogFragment.show(DialogFragment.java:143)
This happens a lot. Activity is not in the correct state to show a dialog. You can guard yourself with this:
if (!isFinishing() && !isDestroyed()) {
dialog.show();
}