【问题标题】:Android ShowDialog : IllegalStateException: Can not perform this action after onSaveInstanceStateAndroid ShowDialog:IllegalStateException:onSaveInstanceState 后无法执行此操作
【发布时间】:2015-08-06 14:10:34
【问题描述】:

在 Activity 的 runOnUiThread() 中,我试图显示 ProgressDialog。

 FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
 ProgressDialogFragment mProgressDialogFragment = new ProgressDialogFragment();
 mProgressDialogFragment.show(fragmentTransaction, TAG);

这里ProgressDialogFragment 扩展了DialogFragment。我已经在许多设备上对此进行了测试,并且没有发生任何崩溃。但是在华硕中,每当我显示对话框时,我都会经常遇到以下崩溃。华硕的操作系统版本是 4.4.2 。

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
       at android.support.v4.app.FragmentManagerImpl.checkStateLoss(FragmentManager.java:1360)
       at android.support.v4.app.FragmentManagerImpl.enqueueAction(FragmentManager.java:1378)
       at android.support.v4.app.BackStackRecord.commitInternal(BackStackRecord.java:595)
       at android.support.v4.app.BackStackRecord.commit(BackStackRecord.java:574)
       at android.support.v4.app.DialogFragment.show(DialogFragment.java:155)
       at com.trimble.android.trimbleone.activity.ProgressDialogHandlerActivity.showProgressDialog(ProgressDialogHandlerActivity.java:72)
       at com.trimble.android.trimbleone.activity.UICallbackHandlerActivity$processThread$7.run(UICallbackHandlerActivity.java:222)
       at android.os.Handler.handleCallback(Handler.java:733)
       at android.os.Handler.dispatchMessage(Handler.java:95)
       at android.os.Looper.loop(Looper.java:149)
       at android.app.ActivityThread.main(ActivityThread.java:5061)
       at java.lang.reflect.Method.invokeNative(Method.java)
       at java.lang.reflect.Method.invoke(Method.java:515)
       at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:788)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:604)
       at dalvik.system.NativeStart.main(NativeStart.java)

【问题讨论】:

  • 这么多设备是什么?这些设备的版本?
  • @PareshMayani 仅供参考,我进一步编辑的唯一原因是在您提出有问题的编辑建议后进行Reject and Edit
  • @DanielNugent 没问题!我只是格式化了代码以完美理解它并错过了格式化其他必需的东西!
  • @PareshMayani Nexus,LG G3,摩托罗拉,这些设备正在运行棒棒糖版本

标签: android fragment android-dialogfragment illegalstateexception showdialog


【解决方案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);
}

最后,正确的解决方案是(如 cmets 所示)使用:

transaction.commitAllowingStateLoss();

当添加或执行导致ExceptionFragmentTransaction 时。

据我所知,上述解决方案正在修复早期 support.v4 库中的问题。但如果您对此仍有疑问,您还必须阅读 @AlexLockwood 的博客:Fragment Transactions & Activity State Loss

博文摘要(但我强烈建议您阅读):

在蜂窝之前的 onPause() 和蜂窝后的 onStop() 之后,永远不要进行 commit() 交易 在Activity 生命周期方法中提交事务时要小心。使用onCreate()onResumeFragments()onPostResume() 避免在异步回调方法中执行事务 仅在不得已的情况下使用 commitAllowingStateLoss()
更新:要使用 stateLoss 显示 DialogFragment,请使用以下几行。

DialogFragment loadingDialog = createDialog();
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
                    transaction.add(loadingDialog, "loading");
                    transaction.commitAllowingStateLoss();

【讨论】:

  • @Override protected void onSaveInstanceState(Bundle outState) { //不调用 super()。 API 级别 > 11 上的错误。} 这个方法应该添加到扩展 DialogFragment 的类中??
  • 在这行之后 mProgressDialogFragment.show(fragmentTransaction, TAG);我应该添加 transaction.commitAllowingStateLoss(); ??
  • 如果您想在更改配置的同时保存数据,那么您可以调用 onSaveInstanceState() 的超级方法。 transaction.commitAllowingStateLoss() 是解决这个问题的最后一个选项。
  • 当我在 mProgressDialogFragment.show(fragmentTransaction, TAG) 之后添加 transaction.commitAllowingStateLoss() 时,我遇到了以下崩溃。 E/AndroidRuntime:致命异常:主要 java.lang.IllegalStateException:提交已在 android.support.v4.app.BackStackRecord.commitAllowingStateLoss(:578) 的 android.support.v4.app.BackStackRecord.commitInternal(:582) 处调用/跨度>
  • 在调用transaction.commitAllowingStateLoss() 后不要再调用dialog.show()。基本上是同一个调用。这样做可能会给你一个错误,比如 Transaction is already committed.Can't change tag of fragment..... 因为你可能正在调用dialog.show(transaction,"some_new_tag") .
猜你喜欢
  • 2012-12-20
  • 1970-01-01
  • 2015-04-02
  • 2014-10-18
  • 2014-03-05
  • 2016-09-06
  • 2018-01-30
  • 2017-06-21
相关资源
最近更新 更多