onActivityResult 中的操作和“错误在 onSaveInstanceState 之后无法执行此操作”
Posted
技术标签:
【中文标题】onActivityResult 中的操作和“错误在 onSaveInstanceState 之后无法执行此操作”【英文标题】:Actions in onActivityResult and "Error Can not perform this action after onSaveInstanceState" 【发布时间】:2012-08-19 18:17:14 【问题描述】:实现用户可以登录的应用程序我有以下情况:如果用户已登录,则执行操作,否则启动登录活动以获得结果,如果结果是 Activity.RESULT_OK,则执行操作。
我的问题是要执行的操作是显示一个 DialogFragment,但调用
DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);
newFragment.show(ft, "dialog")
在onActivityResult回调中抛出异常:
Caused by: java.lang.IllegalStateException:
Can not perform this action after onSaveInstanceState
那么我该如何解决呢?我正在考虑在那里升旗并在 onResume 中显示对话框,但我认为这个解决方案有点脏
编辑:添加了更多代码(我按照此示例显示 DialogFragment
当用户请求操作时:
...
if (!user.isLogged())
startActivityForResult(new Intent(cnt, Login.class), REQUEST_LOGIN_FOR_COMMENT);
在同一个片段中
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_LOGIN_FOR_COMMENT && resultCode == Activity.RESULT_OK)
FragmentTransaction ft = getFragmentManager().beginTransaction();
DialogFragment newFragment = MyDialogFragment.newInstance();
newFragment.show(ft, "dialog")
如果用户登录登录活动调用;
setResult(Activity.RESULT_OK);
finish();
【问题讨论】:
我认为您应该发布整个代码。似乎您正试图在 onpause 后显示对话框 查看androiddesignpatterns.com/2013/08/… 了解为什么会发生这种情况 【参考方案1】:我想出的最好的办法是不使用 .show() 而是这样做。
CheckinSuccessDialog dialog = new CheckinSuccessDialog();
//dialog.show(getSupportFragmentManager(), null);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(dialog, null);
ft.commitAllowingStateLoss();
【讨论】:
虽然它对我有用,但我觉得不安全,因为我们遗漏了 2 个变量:mDismissed = false; mShownByMe = 真;以上变量在原show函数中修改。 mDismissed 和 mShowByMe 似乎是专门用于跟踪对话框是否被外部调用显示/隐藏的变量。换句话说,他们正好补偿了这种事情。 如何“删除”对话框 你有没有试过在activityOnResult的第一行调用super.onActivityResult()? 调用super.onActivityResult()
为我解决了这个问题,在解决之前尝试一下。【参考方案2】:
这是对我来说很好的解决方法。
private void alert(final String message)
Handler handler = new Handler(Looper.getMainLooper());
handler.post(new Runnable()
public void run()
AlertDialogFragment alertDialogFragment = AlertDialogFragment.newInstance(message);
alertDialogFragment.show(getFragmentManager(), ALERT_DIALOG_FRAGMENT);
);
【讨论】:
【参考方案3】:如果使用 DialogFragment,唯一对我有用的是使用 dissmissAllowingStateLoss() 关闭 Fragment
【讨论】:
【参考方案4】:我只是检查一个活动是否正在被销毁。
if (!getActivity().isFinishing())
DialogFragment fragment = MyFragment.newInstance();
fragment.show(getActivity().getSupportFragmentManager(), MyFragment.TAG);
另见https://***.com/a/41813953/2914140。在DialogFragment
写:
override fun show(manager: FragmentManager?, tag: String?)
try
val ft = manager?.beginTransaction()
ft?.add(this, tag)
ft?.commitAllowingStateLoss()
catch (ignored: IllegalStateException)
【讨论】:
【参考方案5】:覆盖show(Fragment manager, String tag)
函数,允许状态丢失并通过反射从原始函数更改mDismissed = false;
mShownByMe = true;
:
public class DialogParent extends DialogFragment
@Override
public void show(FragmentManager manager, String tag)
try
Field mDismissed = DialogFragment.class.getDeclaredField("mDismissed");
Field mShownByMe = DialogFragment.class.getDeclaredField("mShownByMe");
mDismissed.setAccessible(true);
mShownByMe.setAccessible(true);
mDismissed.setBoolean(this, false);
mShownByMe.setBoolean(this, true);
catch (NoSuchFieldException e)
e.printStackTrace();
catch (IllegalAccessException e)
e.printStackTrace();
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
ft.commitAllowingStateLoss();
【讨论】:
你也可以用 try-catch 包围父 show 方法,在 catch 中添加对话框并使用你的事务调用commitAllowingStateLoss()
。这样你就不需要任何反思了。【参考方案6】:
这确实有效。
CheckinSuccessDialog dialog = new CheckinSuccessDialog();
//dialog.show(getSupportFragmentManager(), null);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(dialog, null);
ft.commitAllowingStateLoss();
但还是很糟糕,因为出现错误“活动已被销毁”
ava.lang.IllegalStateException: Activity has been destroyed fragmentTransaction.commitAllowingStateLoss();
所以我的解决方案是添加检查if (!isFinishing()&&!isDestroyed())
CheckinSuccessDialog fragment = CheckinSuccessDialog.newInstance();
if (fragment instanceof DialogFragment)
DialogFragment dialog = (DialogFragment) fragment;
if (!dialog.isAdded())
fragmentTransaction.add(dialog,
CheckinSuccessDialog.class.getName());
if (!isFinishing()&&!isDestroyed())
fragmentTransaction.commitAllowingStateLoss();
解雇时:
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
Fragment fragment = getSupportFragmentManager().findFragmentByTag(CheckinSuccessDialog.class.getName());
if (fragment != null && fragment instanceof DialogFragment)
DialogFragment dialog = (DialogFragment) fragment;
dialog.dismiss();
if (!isFinishing()&&!isDestroyed())
fragmentTransaction.commitAllowingStateLoss();
【讨论】:
【参考方案7】:只要在FragmentManager
保存其状态后提交FragmentTrasaction
,就会引发此异常。简单明了的方法是在显示DialogFragment
之前检查FragmentManager
是否已经保存状态。
if(!getSupportFragmentManager.isStateSaved())
MyDialogFragment dialogFragment = new MyDialogFragment()
dialogFragment.show(getSupportFragmentManager, TAG);
【讨论】:
【参考方案8】:您应该在显示对话框之前调用super.onActivityResult()
【讨论】:
以上是关于onActivityResult 中的操作和“错误在 onSaveInstanceState 之后无法执行此操作”的主要内容,如果未能解决你的问题,请参考以下文章
IllegalStateException:在 onSaveInstanceState 和 onActivityResult 之后无法执行此操作
将 OnActivityResult 数据从电容器传回混合应用程序