IllegalStateException: Can not perform this action

2018-12-31 13:59发布

I'm getting user reports from my app in the market, delivering the following exception:

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
at android.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1109)
at android.app.FragmentManagerImpl.popBackStackImmediate(FragmentManager.java:399)
at android.app.Activity.onBackPressed(Activity.java:2066)
at android.app.Activity.onKeyUp(Activity.java:2044)
at android.view.KeyEvent.dispatch(KeyEvent.java:2529)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1855)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1277)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.widget.TabHost.dispatchKeyEvent(TabHost.java:297)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1112)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:1855)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1277)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1803)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2880)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2853)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2028)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4028)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:491)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
at dalvik.system.NativeStart.main(Native Method)

Apparently it has something to do with a FragmentManager, which I don't use. The stacktrace doesn't show any of my own classes, so I have no idea where this exception occurs and how to prevent it.

For the record: I have a tabhost, and in each tab there is a ActivityGroup switching between Activities.

28条回答
谁念西风独自凉
2楼-- · 2018-12-31 14:26

Starting from support library version 24.0.0 you can call FragmentTransaction.commitNow() method which commits this transaction synchronously instead of calling commit() followed by executePendingTransactions(). As documentation says this approach even better:

Calling commitNow is preferable to calling commit() followed by executePendingTransactions() as the latter will have the side effect of attempting to commit all currently pending transactions whether that is the desired behavior or not.

查看更多
牵手、夕阳
3楼-- · 2018-12-31 14:27

I know there is an accepted answer by @Ovidiu Latcu but after some while, error still persist.

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

Crashlytics still sending me this weird error message.

However error now occurring only on version 7+ (Nougat) My fix was to use commitAllowingStateLoss() instead of commit() at the fragmentTransaction.

This post is helpful for commitAllowingStateLoss() and never had a fragment issue ever again.

To sum it up, the accepted answer here might work on pre Nougat android versions.

This might save someone a few hours of searching. happy codings. <3 cheers

查看更多
呛了眼睛熬了心
4楼-- · 2018-12-31 14:28

If you are doing some FragmentTransaction in onActivityResult what you can do you can set some boolean value inside onActivityResult then in onResume you can do your FragmentTransaction on the basis of the boolean value. Please refer the code below.

@Override
protected void onResume() {
    super.onResume;
    if(isSwitchFragment){
        isSwitchFragment=false;
        bottomNavigationView.getTabAt(POS_FEED).select();
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == FilterActivity.FILTER_REQUEST_EVENT && data != null) {
        isSwitchFragment=true;
    }
}
查看更多
闭嘴吧你
5楼-- · 2018-12-31 14:28

To bypass this issue, we can use The Navigation Architecture Component , which was introduced in Google I/O 2018. The Navigation Architecture Component simplifies the implementation of navigation in an Android app.

查看更多
姐姐魅力值爆表
6楼-- · 2018-12-31 14:30

I found a dirty solution for this kind of problem. If you still want to keep your ActivityGroups for whatever reason (I had time limitation reasons), you just implement

public void onBackPressed() {}

in your Activity and do some back code in there. even if there is no such Method on older Devices, this Method gets called by newer ones.

查看更多
时光乱了年华
7楼-- · 2018-12-31 14:31

Possibly the smoothest and the simplest solution I found in my case was to avoid popping the offending fragment off the stack in response to activity result. So changing this call in my onActivityResult():

popMyFragmentAndMoveOn();

to this:

new Handler(Looper.getMainLooper()).post(new Runnable() {
    public void run() {
        popMyFragmentAndMoveOn();
    }
}

helped in my case.

查看更多
登录 后发表回答