IllegalStateException:使用ViewPager在onSaveInstanceState之后无法执行此操作

我与影子孤独终老i 提交于 2020-02-26 01:07:41

我从市场上的应用程序中获取用户报告,但出现以下异常:

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)

显然,它与FragmentManager有关,我不使用。 stacktrace不显示我自己的任何类,因此我不知道发生此异常的位置以及如何防止它。

作为记录:我有一个tabhost,在每个选项卡中都有一个ActivityGroup在Activity之间切换。


#1楼

在这里检查我的答案。 基本上我只需要:

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

不要在saveInstanceState方法上调用super() 。 这太糟了...

这是支持包中的一个已知错误

如果需要保存实例并向outState Bundle添加一些东西,则可以使用以下命令:

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

最后,可以使用适当的解决方案(如注释中所示):

transaction.commitAllowingStateLoss();

添加或执行导致ExceptionFragmentTransaction


#2楼

这是解决此问题的另一种方法。

使用私有成员变量,您可以将返回的数据设置为意图,然后可以在super.onResume();之后进行处理。

像这样:

private Intent mOnActivityResultIntent = null; 

@Override
protected void onResume() {
    super.onResume();
    if(mOnActivityResultIntent != null){
        ... do things ...
        mOnActivityResultIntent = null;
    }
 }

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
    if(data != null){
        mOnActivityResultIntent = data;
    }
}

#3楼

简短而有效的解决方案:

遵循简单的步骤

脚步

步骤1:在各个片段中覆盖onSaveInstanceState状态。 并从中删除超级方法。

 @Override
public void onSaveInstanceState( Bundle outState ) {

}  

第2步:使用fragmentTransaction.commitAllowingStateLoss( );

而不是fragmentTransaction.commit( ); 而片段操作。


#4楼

当我按“后退”按钮取消地图片段活动中的意图选择器时,出现此异常。 我通过将onResume(我在其中初始化片段的代码)替换为onstart()来解决此问题,该应用程序运行正常。希望它会有所帮助。


#5楼

有许多类似的错误消息相关的问题。 检查此特定堆栈跟踪的第二行。 该异常与FragmentManagerImpl.popBackStackImmediate的调用特别相关。

如果已保存会话状态,则此方法调用(如popBackStack )将始终失败,并出现IllegalStateException 。 检查源。 您无法阻止该异常被抛出。

  • 删除对super.onSaveInstanceState的调用将无济于事。
  • 使用commitAllowingStateLoss创建片段将无济于事。

这是我观察问题的方式:

  • 有一个带有提交按钮的表单。
  • 单击该按钮后,将创建一个对话框并开始异步过程。
  • 用户在处理完成之前单击主键-调用onSaveInstanceState
  • 该过程完成,进行回调并尝试popBackStackImmediate
  • IllegalStateException

这是我为解决该问题所做的工作:

由于不可能在回调中避免IllegalStateException ,因此请捕获并忽略它。

try {
    activity.getSupportFragmentManager().popBackStackImmediate(name);
} catch (IllegalStateException ignored) {
    // There's no way to avoid getting this if saveInstanceState has already been called.
}

这足以阻止应用崩溃。 但是现在,用户将还原该应用程序,并发现根本没有按下他们认为已按下的按钮(他们认为)。 表单片段仍在显示!

为了解决这个问题,在创建对话框时,请设置一些状态以指示进程已开始。

progressDialog.show(fragmentManager, TAG);
submitPressed = true;

并将此状态保存在捆绑包中。

@Override
public void onSaveInstanceState(Bundle outState) {
    ...
    outState.putBoolean(SUBMIT_PRESSED, submitPressed);
}

不要忘记在onViewCreated再次加载它

然后,在恢复时,如果先前尝试过提交,则回滚片段。 这样可以防止用户返回未提交的表单。

@Override
public void onResume() {
    super.onResume();
    if (submitPressed) {
        // no need to try-catch this, because we are not in a callback
        activity.getSupportFragmentManager().popBackStackImmediate(name);
        submitPressed = false;
    }
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!