当应用程序恢复时,被解除的对话框片段会再次出现

时间:2014-12-20 12:36:40

标签: android android-fragments android-fragmentactivity android-dialogfragment

您好我正在开发一个使用地图的应用。

我正在使用Fragment Activity和一个名为Fragment-A的片段。

在Fragment-A中有一个按钮,当点击该按钮弹出一个Dialog Fragment时,会显示一个地图,其中包含先前从服务器收到的某个位置。

让我们说这个对话框片段是DialogFragment-B。

它有一个关闭的按钮,一个导航到谷歌地图应用程序以获取路线的按钮。

如果用户导航到DialogFragment-B并返回到Fragment-A,通过单击关闭按钮,每个东西都能正常工作。

但是如果用户点击后退按钮,现有的对话框片段将正常关闭,应用程序正常运行。

但是,如果用户然后按下主页按钮或接到电话呼叫,并且即使DialogFragment-B之前被解除,也会调用onResume,它会重新出现并按下close会使应用程序出现空指针异常

这是我打开DialogFragment-B的代码。

FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    android.app.Fragment prev = fm.findFragmentByTag(MY_MAP);
    if (prev != null) {
        ft.remove(prev);
    }
    MyMapFragmentDialog newFragment = MyMapFragmentDialog
            .newInstance(eachPost);
    newFragment.show(ft, MY_MAP);

在DialogFragment-B中单击关闭按钮,我调用MyMapFragmentDialog.this.dismiss();

如果有人遇到过这个问题并且克服了这个问题,请指导我。

2 个答案:

答案 0 :(得分:13)

我遇到了同样的问题,确保我在super.onDismiss(dialog)子类的onDismiss方法中调用DialogFragment来解决问题。

答案 1 :(得分:2)

更新:Kalina的答案是一个更优雅,更简单的解决方案 - 正如我后来想到的那样!

我在我的一个应用程序中面临同样的问题,并且没有在任何地方找到答案,请查看DialogFragment类的源代码,该类可在以下位置获得:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/app/DialogFragment.java#DialogFragment.onDismiss%28android.content.DialogInterface%29

然后,我在onDismiss(DialogInterface对话框)方法的源代码中找到了在注释中写的可能原因:

// Note: we need to use allowStateLoss, because the dialog
// dispatches this asynchronously so we can receive the call
// after the activity is paused.  Worst case, when the user comes
// back to the activity they see the dialog again.

我从中理解的是解雇是保存到实例状态,当活动恢复时,它会立即再次显示它作为实例状态恢复的一部分 - 假设片段是永远不会被解雇。作为异步事件,没有安全的方法来提交解雇而不冒险

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

异常和随之而来的崩溃,这可能是班级作者选择这样做的原因。

适用于我的解决方案 是通过以下方式分别监控DialogFragment的状态:

  • 将其存储在Class变量中(此处称为“对话框”)
  • 覆盖onDismiss(DialogInterface对话框)方法和
  • 将布尔dialogDismissed标志设置为true

-

@Override
public void onDismiss(DialogInterface dialog) {
   // dialogDismissed is a Class level variable in the containing Activity,
   // must be set to false each time the DialogFragment is shown
   dialogDismissed = true;
}
  • 注意:如果DialogFragment是一个单独的类,则需要从onDismiss调用Activity中的方法来执行此操作,可能是通过设置接口

  • 然后必须在活动onResume()中检查此标志并强制关闭(在检查对话框不为空之后):

-

@Override
public void onResume() {
super.onResume();
//...
if (dialogDismissed && dialog != null) {
        dialog.dismiss();
    }    
}