我有一个Live Android应用程序,从市场上我收到了以下堆栈跟踪,我不知道为什么它会发生,因为它不是发生在应用程序代码中,而是由应用程序的一些或其他事件引起的(假设)

我没有使用片段,仍然有一个FragmentManager的参考。 如果有人能揭示一些隐藏的事实,以避免这类问题:

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.onKeyDown(Activity.java:1962)
at android.view.KeyEvent.dispatch(KeyEvent.java:2482)
at android.app.Activity.dispatchKeyEvent(Activity.java:2274)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
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.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:1720)
at com.android.internal.policy.impl.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1258)
at android.app.Activity.dispatchKeyEvent(Activity.java:2269)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1668)
at android.view.ViewRoot.deliverKeyEventPostIme(ViewRoot.java:2851)
at android.view.ViewRoot.handleFinishedEvent(ViewRoot.java:2824)
at android.view.ViewRoot.handleMessage(ViewRoot.java:2011)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:132)
at android.app.ActivityThread.main(ActivityThread.java:4025)
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:841)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:599)
at dalvik.system.NativeStart.main(Native Method)  

当前回答

这发生在你试图加载一个片段,但活动已改变其状态为onPause()。例如,当您试图获取数据并将其加载到活动中,但当用户单击某个按钮并移动到下一个活动时,就会发生这种情况。

你可以用两种方法解决这个问题

您可以使用transaction.commitAllowingStateLoss()而不是transaction.commit()来加载片段,但您可能最终会丢失已完成的提交操作。

or

在加载片段时,确保活动处于恢复状态,而不是进入暂停状态。 创建一个布尔值并检查activity是否不进入onPause()状态。

@Override
public void onResume() {
    super.onResume();
    mIsResumed = true;
}

@Override
public void onPause() {
    mIsResumed = false;
    super.onPause();
}

然后,而加载片段检查活动是否存在,只有当活动是前景时才加载。

if(mIsResumed){
 //load the fragment
}

其他回答

这是我迄今为止遇到的最愚蠢的错误。我有一个片段应用程序工作完美的API < 11,并强制关闭API > 11。

我真的不知道他们在saveInstance调用的活动生命周期内改变了什么,但我在这里是我如何解决这个问题的:

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

我只是不调用.super(),一切都很好。我希望这将为您节省一些时间。

编辑:经过进一步研究,这是支持包中的一个已知错误。

如果你需要保存实例,并添加一些东西到你的outState Bundle,你可以使用以下方法:

@Override
protected void onSaveInstanceState(Bundle outState) {
    outState.putString("WORKAROUND_FOR_BUG_19917_KEY", "WORKAROUND_FOR_BUG_19917_VALUE");
    super.onSaveInstanceState(outState);
}

EDIT2:如果您试图在Activity在后台消失后执行事务,也可能会发生这种情况。为了避免这种情况,你应该使用commitAllowingStateLoss()

EDIT3: The above solutions were fixing issues in the early support.v4 libraries from what I can remember. But if you still have issues with this you MUST also read @AlexLockwood 's blog : Fragment Transactions & Activity State Loss Summary from the blog post (but I strongly recommend you to read it) : NEVER commit() transactions after onPause() on pre-Honeycomb, and onStop() on post-Honeycomb Be careful when committing transactions inside Activity lifecycle methods. Use onCreate(), onResumeFragments() and onPostResume() Avoid performing transactions inside asynchronous callback methods Use commitAllowingStateLoss() only as a last resort

我发现,如果另一个应用程序是对话类型,并允许触摸被发送到后台应用程序,那么几乎任何后台应用程序都会崩溃与此错误。 我认为我们需要在每次执行事务时检查实例是否保存或恢复。

My use case: I have used listener in fragment to notify activity that some thing happened. I did new fragment commit on callback method. This works perfectly fine on first time. But on orientation change the activity is recreated with saved instance state. In that case fragment is not created again implies that the fragment have the listener which is old destroyed activity. Any way the call back method will get triggered on action. It goes to destroyed activity which cause the issue. The solution is to reset the listener in fragment with current live activity. This solve the problem.

当用户旋转屏幕以便加载与新方向相关的资源时,onSaveInstance将被调用。

有可能这个用户旋转了屏幕,然后按了后退按钮(因为也有可能这个用户在使用你的应用程序时摸不着他们的手机)

如果你试图在你的片段活动的onSaveInstanceState()被调用后执行片段转换,就会发生这样的异常。

发生这种情况的一个原因是,当一个活动停止时,如果你让一个AsyncTask(或线程)运行。

调用onSaveInstanceState()后的任何转换都可能丢失,如果系统回收活动的资源并稍后重新创建它。