Как правильно отклонить DialogFragment?

Документы говорят это для метода dismiss() из класса Dialog:

Закрыть этот диалог, убрав его с экрана. Этот метод может быть безопасно вызван из любого потока. Обратите внимание, что вам не следует переопределять этот метод для очистки после onStop() диалогового окна, вместо этого реализуйте это в onStop().

В моем коде все, что я делаю, это вызываю getDialog().dismiss() чтобы закрыть его. Но я больше ничего не делаю и даже не использую onStop(). Поэтому я спрашиваю, как именно закрыть DialogFragment чтобы избежать утечек памяти и т.д.

Ответ 1

tl; dr: Правильный способ закрыть DialogFragment - использовать dismiss() непосредственно в диалоговом окне DialogFragment.


Подробнее. документация состояния DialogFragment

Контроль диалога (выбор, когда показывать, скрывать, отклонять его) должен выполняться через API здесь, а не с прямыми вызовами в диалоговом окне.

Таким образом, вы не должны использовать getDialog().dismiss(), так как это вызовет dismiss() в диалоговом окне. Вместо этого вы должны использовать метод dismiss() самого DialogFragment:

public void reject()

Отключите фрагмент и его диалог. Если фрагмент был добавлен в задний стек, будет выведено все состояние предыдущего стека до и включая эту запись. В противном случае будет предпринята новая транзакция для удаления фрагмента.

Как вы можете видеть, это не только закрывает диалог, но и обрабатывает транзакции фрагментов, участвующие в этом процессе.

Вам нужно использовать onStop, если вы явно создали какие-либо ресурсы, требующие ручной очистки (закрытие файлов, закрытие курсоров и т.д.). Даже тогда я бы переопределил onStop диалогового окна DialogFragment, а не onStop базового диалога.

Ответ 2

Я думаю, что лучший способ закрыть DialogFragment это:

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

Таким образом, вам не нужно держать ссылку на DialogFragment и вы можете закрыть его из DialogFragment.

Ответ 3

Вы должны отклонить вас Dialog в onPause(), чтобы переопределить его.

Также перед увольнением вы можете проверить null и показывать как ниже фрагмент:

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

Ответ 4

Я отдал ответ Терелу. Я просто хотел опубликовать это для любых пользователей Kotlin:

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

Ответ 5

Котлинская версия ответа Тереля

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

Ответ 6

Почему бы вам не попробовать использовать только этот код:

dismiss();

Если вы хотите удалить фрагмент диалога самостоятельно. Вы можете просто поместить этот код внутри фрагмента диалога, где вы хотите закрыть диалог.

Например:

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

Это закроет последний фрагмент диалога, который отображается на экране.

Надеюсь, это поможет вам.

Ответ 7

Просто вызовите dismiss() из фрагмента, который вы хотите удалить.

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

Ответ 8

В других ответах есть ссылки на официальные документы (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);

Ответ 9

чуть ниже код в порядке!

dismiss();