【问题标题】:Actions in onActivityResult and "Error Can not perform this action after onSaveInstanceState"onActivityResult 中的操作和“错误在 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();

【问题讨论】:

标签: java android android-fragments


【解决方案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://stackoverflow.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()

            【讨论】:

              猜你喜欢
              • 2019-05-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-04-02
              • 2014-10-18
              相关资源
              最近更新 更多