Android DialogFragment исчезает после изменения ориентации

У меня есть класс v4 класса FragmentActivity, который реализует фрагменты двух сторон (вроде gmail) и кнопку, которая может вызвать диалоговое окно.

Все это отлично работает, если у меня нет изменений ориентации. Когда у меня меняется ориентация, состояния фрагментов не сохраняются.

И главная проблема в том, что если у меня есть FragmentDialog open, он просто исчезает.

Я установил setRetainInstance(true); Во всех фрагментах, но это не помогло.

В моем манифесте я включил android:configChanges="orientation" но по-прежнему не помогает.

Вот мои образцы кода, спасибо за помощь.

 public class AddMasterDialog extends DialogFragment { private int mTitle; private int mPrompt; private OnClickListener onSaveListener; private OnClickListener onCancelListener; public AddMasterDialog newInstance(int title, int prompt) { AddMasterDialog simpleDialog = new AddMasterDialog(title, prompt); return simpleDialog; } public AddMasterDialog() { // Empty constructor required for DialogFragment } public AddMasterDialog(int title, int prompt) { // Empty constructor required for DialogFragment mTitle = title; mPrompt = prompt; } public void setSaveButton(OnClickListener save){ onSaveListener = save; } public void setCancelButton(OnClickListener cancel){ onCancelListener = cancel; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setRetainInstance(true); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //if(savedInstanceState == null){ View view = inflater.inflate(R.layout.add_new_simple, container); getDialog().setTitle(mTitle); ((TextView) view.findViewById(R.id.add_simple_new_value_prompt)).setText(mPrompt); Button saveButton = (Button) view.findViewById(R.id.add_simple_save_button); saveButton.setOnClickListener(onSaveListener); //Cancel Button Button cancelButton = (Button) view.findViewById(R.id.add_simple_cancel_button); cancelButton.setOnClickListener(onCancelListener); return view; //} } } 

И в моей основной деятельности:

 private void initiateAddMasterPopupWindow() { try { addMasterDialog = new AddMasterDialog(R.string.add_new_master_dialog_title, R.string.add_master_new_value_prompt); addMasterDialog.setSaveButton(saveNewMasterClickListener); addMasterDialog.setCancelButton(cancelNewMasterClickListener); FragmentManager fm = getSupportFragmentManager(); addMasterDialog.show(fm, ADD_NEW_MASTER); } catch (Exception e) { e.printStackTrace(); } } 

Хорошо, поэтому проблема DialogFragment с библиотекой совместимости DialogFragment .

Проблема была описана в этом сообщении.

«Устаревшее сообщение DISMISS для фрагмента сохраняется в очереди сообщений. Оно было поставлено в очередь с помощью DialogFragment.onDestroyView() при DialogFragment.onDestroyView() старого диалога и активируется после создания нового диалогового окна.

Быстрое (и, возможно, грязное) обходное решение – переопределить onDestroyView() и очистить слушателя увольнения перед вызовом super.onDestroyView() "

Добавление следующего кода в мой DialogFragment решило проблему:

  @Override public void onDestroyView() { if (getDialog() != null && getRetainInstance()) { getDialog().setDismissMessage(null); } super.onDestroyView(); } 

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

  1. Если вы вызываете Activity onSaveInstanceState() , убедитесь, что вы вызываете Activity onSaveInstanceState() !!!! , В моем случае это был ключ. Также убедитесь, что вы делаете то же самое в Фрагменте.
  2. Если вы используете setRetainInstance , вам нужно будет вручную сохранить значения и повторно применить их. В противном случае вы сможете не беспокоиться об этом, в большинстве случаев. Если вы делаете что-то более сложное, вам может потребоваться setRetainInstance(true) , но в противном случае игнорировать его. В моем случае мне нужно было использовать его для хранения случайного семестра для одного из моих классов, но в остальном я был в порядке.
  3. Некоторые люди жаловались на ошибку в библиотеке поддержки, где отправляется сообщение об увольнении, когда этого не должно быть. По-видимому, последняя библиотека поддержки исправила это, поэтому вам не стоит беспокоиться об этом.

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

В моем случае у меня был DialogFragment, показывающий другой DialogFragment, используя

 listDialogFragment.show(getChildFragmentManager(), "TAG"); 

Изменение его на

 listDialogFragment.show(getActivity().getSupportFragmentManager(), "TAG"); 

Исправлена ​​проблема

В дополнение к установке setRetainInstance(true); Просто поместите следующий код в свой DialogFragment . Это проверенное решение.

 private boolean isDismissible = false; @Override public void dismiss() { try { isDismissible = true; super.dismiss(); Log.d(getClass().getSimpleName(), "Dialog dismissed!"); } catch (IllegalStateException ilse) { } } @Override public void onDismiss(DialogInterface dialog) { // So that dialog should not dismiss on orientation change if (isDismissible) { // So that dialog can be dismissed super.onDismiss(dialog); } }