如何正确解雇DialogFragment?

时间:2012-06-26 05:05:52

标签: android android-dialogfragment

文档为dismiss()类的Dialog方法说明了这一点:

  

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

在我的代码中,我所做的只是致电getDialog().dismiss()来解雇它。但我没有做任何其他事情,甚至没有使用onStop()。所以我问到究竟如何正确解雇DialogFragment以避免任何内存泄漏等等。

13 个答案:

答案 0 :(得分:168)

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


详情documentation of DialogFragment

  

控制对话框(决定何时显示,隐藏,关闭它)应该通过API在这里完成,而不是直接调用对话框。

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

  

public void dismiss()

     

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

正如您所看到的,这不仅关闭对话框,还关注处理流程中涉及的片段事务。

如果您明确创建了需要手动清理的任何资源(关闭文件,关闭游标等),则只需使用onStop。即使这样,我也会覆盖DialogFragment的onStop而不是底层Dialog的onStop

答案 1 :(得分:63)

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

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

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

答案 2 :(得分:2)

你应该在Dialog中解雇你onPause(),以便覆盖它。

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

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

答案 3 :(得分:2)

我赞成Terel的回答。我只想将其发布给所有Kotlin用户:

import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
class App extends React.Component {
  render() {
    return (
      <Router>
      <div>
          <Header/>
          <Switch>
              <Route exact path="/" component={Home} />
              <Route path="/blog/:slug" component={Blog} />
              <Route path="/:slug" component={Page} />
          </Switch>
          <Footer/>
      </div>
      </Router>
    );
  }
}

答案 4 :(得分:2)

泰瑞尔答案的科林版

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

答案 5 :(得分:2)

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

dismiss();

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

例如:

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

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

希望对您有帮助。

答案 6 :(得分:1)

CustomFragment dialog = (CustomDataFragment) getSupportFragmentManager().findFragmentByTag("Fragment_TAG");
if (dialog != null) {
  dialog.dismiss();
}

答案 7 :(得分:1)

除其他答案外,当<template> <div class="app"> <div class="row"> <div class="col-sm" v-for="item in items"> {{ item.prop1 }} </div> </div> </div> </template> <script> import axios from 'axios' export default { name: 'app2', data() { return { items: [] } }, // Fetch items from database... } 全屏调用DialogFragment时,不会从片段堆栈中弹出DialogFragment。一种解决方法是在父活动上调用dismiss()

类似这样的东西:

CustomDialogFragment.kt

onBackPressed()

答案 8 :(得分:0)

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

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

答案 9 :(得分:0)

在其他答案中也有对官方文档(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将负责弹出事务   对话框的对话框与之分开。

出于我的需要,我将其更改为:

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

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

答案 10 :(得分:0)

我发现,当在导航图中使用<fragment>标签定义了我的片段时(对于全屏对话框片段),使用dismiss()命令不会取消对话框片段。相反,我不得不弹出堆栈:

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

但是,如果在导航图中使用<dialog>标签定义了相同的dialogfragment,则dismiss()可以正常工作。

答案 11 :(得分:0)

考虑以下示例代码片段,该代码片段演示了如何安全地关闭对话框片段:

DialogFragment dialogFragment = new DialogFragment();

/** 
 * do something
 */

// Now you want to dismiss the dialog fragment
if (dialogFragment.getDialog() != null && dialogFragment.getDialog().isShowing())
{
    // Dismiss the dialog
    dialogFragment.dismiss();
}

快乐编码!

答案 12 :(得分:0)

这里是一个简单的AppCompatActivity扩展函数,它关闭打开的Dialog Fragment:

process run_pr {

echo true
container 'docimage:1.0.0'

publishDir "${params.outDir}", mode: 'copy'

output:
file '*' into output_ch

script:
"""
Rscript /home/project/scripts/run.R -s "$params.inputDir" -i "$params.inputFile"
"""
}



process latexGen {

echo true
container 'docimage:1.0.0'

input:
file '*' from output_ch

output:
publishDir "${params.outDir}", mode: 'copy'
    
script:
"""
pdflatex -output-directory=/home/project/$params.outDir  /home/project/scripts/doc.tex
"""
}

当然,您可以直接从任何活动中调用它。 如果你需要从 Fragment 调用它,只需对 Fragment 类做相同的扩展函数