it-roy-ru.com

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

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

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

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

98
Andy

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


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

Управление диалогом (решение о том, когда показывать, скрывать, отклонять его) должно осуществляться через API, а не с помощью прямых вызовов диалога.

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

public void dismiss ()

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

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

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

162
Heinzi

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

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

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

61
Terel

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

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

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

dismiss();

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

Например:

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

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

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

2
Shiva Tiwari

Вы должны уволить вас Dialog в onPause(), поэтому переопределите его.

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

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

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

(fragmentManager.findFragmentByTag(TAG) as? DialogFragment)?.dismiss()
1
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