如何正确消除DialogFragment?


121

文档针对类中的dismiss()方法说了这一点Dialog

退出此对话框,将其从屏幕上删除。可以从任何线程安全地调用此方法。请注意,关闭对话框时,您不应覆盖此方法进行清理,而应在中实现该方法onStop()

在我的代码中,我要做的只是调用getDialog().dismiss()以将其消除。但是我什么也没做,甚至没有使用onStop()。所以我确切地问如何正确消除a DialogFragment以避免任何内存泄漏等。

Answers:


197

tl; dr:关闭a的正确方法DialogFragmentdismiss() 直接在DialogFragment上使用。


详细信息DialogFragment状态的文档

对话框的控制(决定何时显示,隐藏,关闭它)应该通过此处的API来完成,而不是直接在对话框上进行调用。

因此,您不应使用getDialog().dismiss(),因为那样会dismiss() 在dialog上调用。相反,您应该使用dismiss()DialogFragment本身的方法:

公共无效dismiss()

关闭片段及其对话框。如果将片段添加到后堆栈,则将弹出直至该条目的所有后堆栈状态。否则,将提交一个新事务以删除该片段。

如您所见,这不仅需要关闭对话框,还需要处理流程中涉及的片段事务。

onStop当您明确创建了需要手动清除的资源(关闭文件,关闭游标等)时,才需要使用。即使这样,我还是会覆盖onStopDialogFragment而不是onStop基础Dialog。


1
@ScootrNova:不应该,您可能在其他地方有一个错误。您如何创建片段?
Heinzi 2014年

protected void showDialogFragment(final DialogFragment fragment) {final FragmentTransaction fTransaction = getSupportFragmentManager().beginTransaction(); fTransaction.addToBackStack(null); fragment.show(fTransaction, "dialog");} 对不起,令人讨厌的一班轮!但是,是的,您可能是对的,因此暂时我已经写出了另一种关闭DialogFragments的方法。我使用dismiss()方法消除它们的方式是按标签查找片段,然后在不为null的情况下对其运行dismiss()。哦,是的,我正在new将片段传递给该方法之前。
Charles Madere 2014年

2
@ScootrNova:嗯,看不到有什么问题-另一方面,我从未使用过兼容性库,因此我不确定。创建一个最小的,独立的示例并对此提出一个新的问题也许是有意义的。
Heinzi 2014年

那时@CharlesMadere,您找到解决方案了吗?
JCarlosR

抱歉@JCarlos,这是几年前的事,我不确定。
查尔斯·马德雷

76

我认为关闭a的更好方法DialogFragment是:

Fragment prev = getSupportFragmentManager().findFragmentByTag("fragment_dialog");
if (prev != null) {
    DialogFragment df = (DialogFragment) prev;
    df.dismiss();
}

这样,您不必持有对的引用,就DialogFragment可以从任何地方关闭它。


7

为什么不尝试仅使用以下代码:

dismiss();

如果要自行关闭对话框片段。您可以简单地将此代码放在要关闭该对话框的对话框片段中。

例如:

button.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
       dismiss();
   }
});

这将关闭屏幕上显示的最新对话框片段。

希望对您有帮助。


一直没有工作
Mahmoud Heretani

5

我对Terel的回答表示赞同。我只是想将其发布给所有Kotlin用户:

supportFragmentManager.findFragmentByTag(TAG_DIALOG)?.let {
    (it as DialogFragment).dismiss()
}

简单的代码很努力,谢谢您的更新!!
Ayush Katuwal

4

Terel的Kotlin版本答案

(fragmentManager.findFragmentByTag(TAG) as? DialogFragment)?.dismiss()

1

您应该解雇您DialogonPause()以便对其进行覆盖。

另外,在解雇之前,您可以检查null并显示如下代码段所示:

@Override
protected void onPause() {
    super.onPause();
    if (dialog != null && dialog.isShowing()) {
        dialog.dismiss();
    }
}

他已经写过他正在做dismiss()及其有关DialogFragment的文章。
Paresh Mayani

我认为这适用于Dialog和DialogFragments @PareshMayani
Venky

2
我相信@PareshMayani是正确的Venky。DialogFragmentGoogle上的教程完全没有显示onPause()所使用的方法。但是我想我知道你在做什么。但是,如果用户不打电话,那有什么意义呢onPause()?多数民众赞成在系统知道片段正在被调用时。比如说用户取消了。在这种情况下,关闭它的更好方法是什么?
安迪

1

在其他答案中也有对官方文档的引用(DialogFragment Reference),但没有提及此处给出的示例:

void showDialog() {
    mStackLevel++;

    // DialogFragment.show() will take care of adding the fragment
    // in a transaction.  We also want to remove any currently showing
    // dialog, so make our own transaction and take care of that here.
    FragmentTransaction ft = getFragmentManager().beginTransaction();
    Fragment prev = getFragmentManager().findFragmentByTag("dialog");
    if (prev != null) {
        ft.remove(prev);
    }
    ft.addToBackStack(null);

    // Create and show the dialog.
    DialogFragment newFragment = MyDialogFragment.newInstance(mStackLevel);
    newFragment.show(ft, "dialog");
}

这将删除当前显示的所有对话框,创建带有参数的新DialogFragment,并将其显示为后堆栈上的新状态。弹出事务时,当前的DialogFragment及其Dialog将被销毁,并重新显示前一个(如果有的话)。请注意,在这种情况下,DialogFragment将负责弹出对话框的事务,而Dialog的事务则与之分开。

为了我的需要,我将其更改为:

FragmentManager manager = getSupportFragmentManager();
Fragment prev = manager.findFragmentByTag(TAG);
if (prev != null) {
    manager.beginTransaction().remove(prev).commit();
}

MyDialogFragment fragment = new MyDialogFragment();
fragment.show(manager, TAG);

1

除了其他答案外,当DialogFragment全屏调用dismiss()时,不会从片段返回堆栈弹出DialogFragment。一种解决方法是调用onBackPressed()父活动。

像这样:

CustomDialogFragment.kt

closeButton.onClick {
    requireActivity().onBackPressed()
}

保存一天,非常感谢
Mahmoud Heretani

0

只需从您要关闭的片段中调用dismiss()即可。

imageView3.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            dismiss();
        }
    });

0

我发现,当我的片段在导航图中使用<fragment>标签定义(对于全屏dialogfragment)时,dialogfragment不会被该dismiss()命令关闭。相反,我不得不弹出后端堆栈:

findNavController(getActivity(), R.id.nav_host_fragment).popBackStack();

但是,如果在导航图中使用<dialog>标签定义了相同的dialogfragment ,则dismiss()效果很好。


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.