web-dev-qa-db-ja.com

DialogFragmentを正しく閉じる方法は?

ドキュメントは、Dialogクラスのdismiss()メソッドに対して次のように述べています。

このダイアログを閉じて、画面から削除します。このメソッドは、任意のスレッドから安全に呼び出すことができます。ダイアログが閉じられたときにクリーンアップを行うためにこのメソッドをオーバーライドするのではなく、代わりにonStop()に実装する必要があることに注意してください。

私のコードでは、getDialog().dismiss()を呼び出してそれを閉じるだけです。しかし、私は他に何もしておらず、onStop()を使用していません。したがって、メモリリークなどを避けるためにDialogFragmentを正しく閉じる方法を正確に求めています。

105
Andy

tl; dr:DialogFragmentを閉じる正しい方法は、dismiss()を使用することですDialogFragmentで直接


詳細DialogFragmentのドキュメント 状態

ダイアログの制御(表示、非表示、終了のタイミングの決定)は、ダイアログの直接呼び出しではなく、ここでAPIを使用して行う必要があります。

したがって、getDialog().dismiss()を使用しないでください。dismiss()ダイアログでが呼び出されるためです。代わりに、DialogFragment自体のdismiss()メソッドを使用する必要があります。

public void dismiss()

フラグメントとそのダイアログを閉じます。フラグメントがバックスタックに追加された場合、このエントリまでのすべてのバックスタック状態がポップされます。それ以外の場合、フラグメントを削除するために新しいトランザクションがコミットされます。

ご覧のとおり、これはダイアログを閉じるだけでなく、プロセスに関係するフラグメントトランザクションの処理にも注意します。

手動クリーンアップ(ファイルを閉じる、カーソルを閉じるなど)を必要とするリソースを明示的に作成した場合にのみ、onStopを使用する必要があります。その場合でも、基になるDialogのonStopではなく、DialogFragmentのonStopをオーバーライドします。

177
Heinzi

DialogFragmentを閉じるより良い方法はこれだと思います:

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

この方法では、DialogFragmentへの参照を保持する必要はなく、どこからでも参照を閉じることができます。

65
Terel

Terelの回答に賛成票を投じました。これをKotlinユーザーに投稿したかっただけです。

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

このコードのみを使用してみませんか?

dismiss();

Dialog Fragmentを単独で閉じる場合。このコードを、ダイアログを閉じるダイアログフラグメント内に配置するだけです。

例えば:

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

これにより、画面に表示されている最近のダイアログフラグメントが閉じます。

お役に立てば幸いです。

3
Shiva Tiwari

onPause()Dialogを閉じる必要があるため、オーバーライドします。

また、閉じる前にnullを確認でき、以下のスニペットのように表示されます。

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

Kotlinバージョン Terelの回答

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

破棄するフラグメントからdismiss()を呼び出すだけです。

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

他の回答には公式ドキュメントへの参照があります( 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);
0
Maksim Ivanov