1)我启动后台任务(通过AsyncTask)
new FindJourneyTask().execute(); // FindJourneyTask extends AsyncTask
2)仍然在主线程中(在新线程启动之前)我创建了一个带有showDialog(dialogId)的对话框
// this method is in FindJourneyTask
protected void onPreExecute() {
showDialog(DIALOG_FINDING_JOURNEY);
}
3)屏幕方向更改并重新创建活动
4)我现在如何从FindJourneyTask中删除对话框?调用dismissDialog(dialogId)什么都不做。
// this method is in FindJourneyTask
protected void onPostExecute(FindJourneyResult result) {
dismissDialog(DIALOG_FINDING_JOURNEY); // does nothing
}
答案 0 :(得分:22)
这是一个常见问题,并没有真正好的解决方案。问题是,在屏幕方向更改时,整个活动将被销毁并重新创建。同时,您在之前使用的Dialog在新的Activity中重新创建,但旧的后台任务在尝试关闭对话框时仍然引用旧的Activity。结果是它解除了一个很久以前被破坏的对话框,而不是忽略了新方向创建的对话框。
有三种基本解决方案:
覆盖默认的方向处理代码,以便在轮换时不会销毁您的活动。这可能是最不令人满意的答案,因为它会阻止大量代码在方向更改时自动运行。
创建一个引用Activity本身的Activity的静态成员变量,以便您可以调用STATIC_ACTIVITY_VARIABLE.dismissDialog()
。
编写一个解决方案,其中后台任务跟踪当前活动并根据需要自行更新。
这里详细讨论了这三种解决方案:http://groups.google.com/group/android-developers/browse_thread/thread/bf046b95cf38832d/
答案 1 :(得分:10)
现在有一个更好的解决方案可以解决使用碎片问题。
如果使用DialogFragment创建对话框,则此片段将负责维护对话框的生命周期。当您显示对话框时,您将为片段提供标记(DialogFragment.show())。当您需要访问对话框时,只需使用FragmentManager.findFragmentByTag查找必要的DialogFragment,而不是引用对话框本身。
这样,如果设备更改方向,您将获得一个新片段而不是旧片段,一切都会正常工作。
这里有一些基于@peresisUser答案的代码:
public void onSaveInstanceState(Bundle outState) {
AppCompatActivity activity = (AppCompatActivity) context;
FragmentManager fragmentManager = activity.getSupportFragmentManager();
DialogFragment dialogFragment = (DialogFragment) fragmentManager.findFragmentByTag("your_dialog_tag");
if(dialogFragment!=null) {
Dialog dialog = dialogFragment.getDialog();
if(dialog!=null && dialog.isShowing()) {
dialogFragment.dismiss();
}
}
}
答案 2 :(得分:4)
这个问题被问到并回答了很久,但我偶然发现了这个问题,并想分享我的解决方案......
我检查onSavedInstance(),它运行方向更改,对话框是否显示dialog.isShowing(),并将其传递给outState变量。然后在你的onCreate()中,检查这个var是否为真。如果是,您只需使用dialog.dismiss()
关闭对话框希望这有助于其他人:()
答案 3 :(得分:1)
我尝试在setRetainInstance(true);
OnCreate
函数上添加DialogFragment
。这将导致对话框在旋转时消失。