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

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

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

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

DialogFragment есть метод, называемый dismissAllowingStateLoss()

Это то, что я сделал (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(); getFragmentManager().beginTransaction().remove(f).commit(); } super.onResume(); } 

Таким образом, диалог будет отклонен, если он будет виден. Если не видно, диалог будет удален далее, фрагмент станет видимым (onResume) …

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

  @Override public void onResume() { super.onResume(); if(fragment_RedemptionPayment.isVisible()){ fragment_RedemptionPayment.dismiss(); } } 

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

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

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