Правильный способ отклонения DialogFragment, когда приложение находится в фоновом режиме

Я начал использовать DialogFragment, потому что они хорошо работают с изменением ориентации и прочим. Но есть неприятная проблема, с которой я столкнулся.

У меня есть AsyncTask, который показывает прогресс DialogFragment и закрывает его onPostExecute. Все работает нормально, за исключением случаев, когда onPostExecute происходит, когда приложение находится в фоновом режиме (например, после нажатия кнопки «Домой»). Затем я получил эту ошибку при отклонении DialogFragment - "Can not perform this action after onSaveInstanceState". Дох. Обычные диалоги работают нормально. Но не Фрагментдиалог.

Итак, мне интересно, как правильно закрыть DialogFragment, когда приложение находится в фоновом режиме? Я не очень много работал с фрагментами, поэтому я думаю, что просто что-то упускаю.


person Sver    schedule 17.02.2012    source источник
comment
см. также здесь хорошее решение с использованием приостановленный обработчик   -  person PJL    schedule 23.04.2012


Ответы (5)


DialogFragment имеет метод под названием dismissAllowingStateLoss()

person Jiang Qi    schedule 23.04.2012
comment
Это работает, только если вы используете: show(FragmentManager, tag), но не при использовании show(FragmentTransaction, tag), потому что popBackStack в dismissInternal вызывает enqueueAction(..., allowStateLoss=false), несмотря на то, что мы просили разрешить потерю состояния. И это происходит как в фреймворке, так и в версии поддержки. - person TWiStErRob; 05.05.2015

Вот что я сделал (df == dialogFragment):

Убедитесь, что вы вызываете диалог следующим образом:

df.show(getFragmentManager(), "DialogFragment_FLAG");

Если вы хотите закрыть диалоговое окно, сделайте эту проверку:

if (df.isResumed()){
  df.dismiss();
}
return;

Убедитесь, что у вас есть следующее в методе onResume() вашего фрагмента (не df)

@Override
public void onResume(){
  Fragment f = getFragmentManager().findFragmentByTag("DialogFragment_FLAG");
  if (f != null) {
    DialogFragment df = (DialogFragment) f;
    df.dismiss();
  }
  super.onResume();
}   

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

person Mohammed Aljarrah    schedule 21.02.2013
comment
Это всегда отклоняет фрагмент, когда пользователь возвращается, что, если они еще не прочитали диалоговое окно, а просто покинули приложение сразу после его отображения? - person TWiStErRob; 05.05.2015
comment
dismiss() уже внутренне удаляет фрагмент диалога. Исходный код: getFragmentManager().beginTransaction(); ft.remove(this); - person Ryan Amaral; 23.07.2018

Вот что мне нужно было сделать, чтобы добиться того, чего вы хотите: у меня есть действие Fragment, в котором я показывал фрагмент диалога с именем fragment_RedemptionPayment, который глобально объявлен вверху. Следующий код отклоняет DialogFragment, если он отображался до того, как активность перешла в фоновый режим и вернулась на передний план.

     @Override
        public void onResume() {
            super.onResume();        
            if(fragment_RedemptionPayment.isVisible()){
                fragment_RedemptionPayment.dismiss();
            }
}
person Shahid Sarwar    schedule 16.04.2017

Еще один новый способ проверки состояния перед вызовом отклонения:

if(!dialog.isStateSaved){
    dialog.dismiss()
} else {
    //Change the UI to suit your functionality
}

Таким образом проверяется, сохраняется состояние или нет, в основном на паузе и вызывается onSaveInstanceState.

Для Java вы можете использовать isStateSaved()

person KnowIT    schedule 11.04.2020

Решение, которое может сработать, — установить Fragment.setRetainInstance(true) в вашем диалоговом фрагменте, но это не самое красивое из исправлений.

Иногда я замечал, что мне приходится ставить диалоговые действия в очередь, чтобы позволить фреймворку сначала восстановить состояние. Если вы можете получить текущий Looper (Activity.getMainLooper()) и обернуть его в Handler, вы можете попробовать передать свое увольнение в конец очереди, разместив runnable в этой очереди.

Я часто заканчиваю тем, что использую отдельный фрагмент, который retaininstance(true) имеет ResultReceiver. Поэтому я передаю этот получатель результатов своим заданиям и обрабатываю обратные вызовы в его onReceive (часто в качестве маршрутизатора для других получателей). Но это может быть немного больше работы, чем оно того стоит, если вы используете асинхронные задачи.

person Sebastian Olsson    schedule 17.02.2012