簡體   English   中英

如何正確關閉 DialogFragment?

[英]How to correctly dismiss a DialogFragment?

文檔針對Dialog類中的dismiss()方法說了這一點:

關閉此對話框,將其從屏幕上移除。 可以從任何線程安全地調用此方法。 請注意,當對話框關閉時,您不應覆蓋此方法來進行清理,而應在onStop()中實現該方法。

在我的代碼中,我所做的就是調用getDialog().dismiss()來關閉它。 但我沒有做任何其他事情,甚至沒有使用onStop() 所以我問的是如何正確關閉DialogFragment以避免任何內存泄漏等。

tl;dr:關閉DialogFragment的正確方法是直接在 DialogFragment 上使用dismiss()


詳細信息DialogFragment 說明的文檔

對話框的控制(決定何時顯示、隱藏、關閉它)應該通過此處的 API 完成,而不是直接調用對話框。

因此,您不應使用getDialog().dismiss() ,因為那樣會在 dialog 上調用dismiss() 相反,您應該使用 DialogFragment 本身的dismiss()方法:

公共無效解雇()

關閉片段及其對話框。 如果片段被添加到返回堆棧,所有返回堆棧狀態直到並包括這個條目將被彈出。 否則,將提交一個新的事務來刪除片段。

如您所見,這不僅會關閉對話框,還會處理流程中涉及的片段事務。

如果您顯式創建了任何需要手動清理的資源(關閉文件、關閉游標等),則只需要使用onStop 即使那樣,我也會重寫 DialogFragment 的onStop而不是基礎 Dialog 的onStop

我認為關閉DialogFragment的更好方法是:

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

這樣您就不必持有對DialogFragment的引用,並且可以從任何地方關閉它。

為什么不嘗試僅使用此代碼:

dismiss();

如果您想自己關閉對話框片段。 您可以簡單地將此代碼放在要關閉對話框的對話框片段中。

例如:

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

這將關閉屏幕上顯示的最近的對話框片段。

希望對你有幫助。

我贊成特雷爾的回答。 我只想為任何 Kotlin 用戶發布這個:

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

Terel 答案的Kotlin 版本

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

您應該在onPause()中關閉Dialog ,以便覆蓋它。

同樣在解散之前,您可以檢查null並顯示如下代碼片段:

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

在其他答案中有對官方文檔( 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);

我發現當我的片段在導航圖中用<fragment>標簽定義時(對於全屏對話框片段),對話框片段不會用dismiss()命令關閉。 相反,我不得不彈出返回堆棧:

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

但是,如果在帶有<dialog>標記的導航圖中定義了相同的 dialogfragment,則dismiss()可以正常工作。

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

添加到其他答案中,當具有全屏調用dismiss()DialogFragment時,不會從片段后台彈出 DialogFragment。 解決方法是在父活動上調用onBackPressed()

像這樣:

自定義對話框片段.kt

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

只需從要關閉的片段中調用 dismiss() 即可。

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

考慮下面的示例代碼片段,它演示了如何安全地關閉對話框片段:

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();
}

快樂編碼!

這是一個簡單的 AppCompatActivity 擴展函數,它關閉打開的對話框片段:

fun AppCompatActivity.whenDialogOpenDismiss(
    tag: String
) {
    supportFragmentManager.findFragmentByTag(tag)?.let { 
        if(it is DialogFragment) it.dismiss() }
}

當然,您可以直接從任何活動中調用它。 如果您需要從 Fragment 調用它,只需對 Fragment 類創建相同的擴展函數

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM