IllegalStateException - Fragment support library

2019-01-19 11:00发布

问题:

I have a serious problem with my App continously crashing on some users devices with the following exception in an Activity onStart method:

Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1299)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1310)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:541)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:525)
at android.support.v4.app.DialogFragment.show(DialogFragment.java:123) 

I cannot reproduce this error locally in my emulator. I have found a few questions regarding this issue on stackoverflow: here and here

I have tried the suggested solution, i.e. do not allow empty bundles in onSaveInstance neither in fragments nor activities.

However the problem remains. This is the only Crash report I ever get, and I get it continously.

Does anyone have a working solution?

回答1:

I have solved this issue by

  • upgrading my support lib to revision 10
  • using workaround posted here: http://code.google.com/p/android/issues/detail?id=23096 i.e.. Add a non-ui fragment in onResumeFragments and invoke further transactions in Listener Callback.

Check my answer here for code: "Can not perform this action after onSaveInstanceState" - why am I getting this exception from my activity's onResume method?

Got no more IllegalStateException so far.



回答2:

I solved this using this workaround, namely put the code into a methods onPostResume() function in the Activity



回答3:

Read This Article.

And,

This one.

Once the issue is understood, go ahead and change things properly:

Figure out why your transactions are happening outside your onResume state. Why are these things happening when they shouldn't be. Why are you manually adding and removing fragments with regard to the lifecycle of you app rather than when the user requests. You should maybe need one time in the onCreate() or when the user invokes something. But why are you messing with them in onResume() in the first place? Don't do that.

If you change all the .commit() to .commitAllowStateLoss() then the crashes will go away. But, you're better off not doing that. You are better off making sure you never change your fragments except when the app is fully live. Sometimes that means never loading a fragment from the OnActivityResult() but rather flagging to run in your onPostResume(), and avoiding performing UI changes in async threads that wrongly assume you couldn't have killed the activity in the meantime.

If you just want to spackle everything, .commitAllowStateLoss() will do that. If you want to do it right, make sure you don't fiddle with your fragments after things die.

One of the more recent forms of Android circa Oreo I think, changed this to avoid this annoying error. My answer seems a bit vague but it's because the bug is in the paradigm. You entirely can hit that with various code elements and fairly routinely.