I have a Live Android application, and from market i have received following stack trace and i have no idea why its happening as its not happening in application code but it
Such an exception will occur if you try to perform a fragment transition after your fragment activity's onSaveInstanceState()
gets called.
One reason this can happen, is if you leave an AsyncTask
(or Thread
) running when an activity gets stopped.
Any transitions after onSaveInstanceState()
is called could potentially get lost if the system reclaims the activity for resources and recreates it later.
I got this issue.But I think this problem is not related to commit and commitAllowStateLoss.
The following stack trace and exception message is about commit().
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1341)
at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1352)
at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
But this exception was caused by onBackPressed()
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.support.v4.app.FragmentManagerImpl.checkStateLoss(Unknown Source)
at android.support.v4.app.FragmentManagerImpl.popBackStackImmediate(Unknown Source)
at android.support.v4.app.FragmentActivity.onBackPressed(Unknown Source)
They were all caused by checkStateLoss()
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);
}
mStateSaved will be true after onSaveInstanceState.
This problem rarely happens.I have never encountered this problem.I can not reoccurrence the problem.
I found issue 25517
It might have occurred in the following circumstances
Back key is called after onSaveInstanceState, but before the new activity is started.
use onStop() in code
I'm not sure what the root of the problem is. So I used an ugly way.
@Override
public void onBackPressed() {
try{
super.onBackPressed();
}catch (IllegalStateException e){
// can output some information here
finish();
}
}
onSaveInstance will be called if a user rotates the screen so that it can load resources associated with the new orientation.
It's possible that this user rotated the screen followed by pressing the back button (because it's also possible that this user fumbled their phone while using your app)
My solution for that problem was
In fragment add methods:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
...
guideMapFragment = (SupportMapFragment)a.getSupportFragmentManager().findFragmentById(R.id.guideMap);
guideMap = guideMapFragment.getMap();
...
}
@Override
public void onDestroyView() {
SherlockFragmentActivity a = getSherlockActivity();
if (a != null && guideMapFragment != null) {
try {
Log.i(LOGTAG, "Removing map fragment");
a.getSupportFragmentManager().beginTransaction().remove(guideMapFragment).commit();
guideMapFragment = null;
} catch(IllegalStateException e) {
Log.i(LOGTAG, "IllegalStateException on exit");
}
}
super.onDestroyView();
}
May be bad, but couldn't find anything better.
I noticed something very interesting. I have in my app the option to open the phone's gallery and the device asks what app to use, there I click on the gray area away from the dialog and saw this issue. I noticed how my activity goes from onPause, onSaveInstanceState back to onResume, it doesn't happen to visit onCreateView. I am doing transactions at onResume. So what I ended up doing is setting a flag being negated onPause, but being true onCreateView. if the flag is true onResume then do onCommit, otherwise commitAllowingStateLoss. I could go on and waste so much time but I wanted to check the lifecycle. I have a device which is sdkversion 23, and I don't get this issue, but I have another one which is 21, and there I see it.
Simply call super.onPostResume() before showing your fragment or move your code in onPostResume() method after calling super.onPostResume(). This solve the problem!