0

I have a DialogFragment that I launch when a user taps a menu item on the ActionBar. Everything about the Dialog functions properly - it launches just fine and it does everything I've set it up to do. Unfortunately, as soon as I rotate my device, the DialogFragment disappears.

This seemed to be a common problem back in 2012 - I've scoured StackOverflow and tried all of the common fixes that have been posted in the last couple of years. This SO post in particular summarizes all of the potential fixes that have been proposed:

  • Set up the DialogFragment to use the newInstance() paradigm
  • Add setRetainInstance(true) to the DialogFragment's onCreate()
  • Add a workaround to onDestroyView() to address a potential bug in the support library

Despite implementing everything above, the DialogFragment refuses to stick around after device rotation.

Here's how I launch the DialogFragment from the Activity:

DialogKanjiLookup dialog = DialogKanjiLookup.newInstance(gSearchView.getQuery());
dialog.show(getSupportFragmentManager(), "dialogKanjiLookup");

Here is the DialogFragment's newInstance():

public DialogKanjiLookup() {}

public static DialogKanjiLookup newInstance(CharSequence searchTerm)
{
    DialogKanjiLookup dialog = new DialogKanjiLookup();
    Bundle args = new Bundle();
    args.putCharSequence(BUNDLE_SEARCH, searchTerm);
    dialog.setArguments(args);
    return dialog;
}

Here's the dialog's `onCreateDialog():

@Override
public Dialog onCreateDialog(Bundle savedInstanceState)
{
    // Specify a layout for the dialog
    LayoutInflater inflater = getActivity().getLayoutInflater();
    View layout = inflater.inflate(R.layout.dialog_kanjilookup, null);

    // SNIP
    // ...Handle savedInstanceState, set up various Listeners and adapters...
    // SNIP

    // Create the actual dialog
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

    // Customize the dialog
    builder.setTitle(R.string.dialog_kanji_lookup_title);
    builder.setIcon(R.drawable.kanji_lookup);
    builder.setPositiveButton(R.string.menu_search, btnSearchListener);
    builder.setNegativeButton(R.string.cancel, null);
    builder.setView(layout);

    // Force the dialog to take up as much space as it can
    Dialog dialog = builder.create();
    dialog.show();
    dialog.getWindow().setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT);

    // Display the dialog
    return dialog;
}

There's only one instance of DialogFragment.dismiss() called from within the fragment but that's only triggered when the user taps one of the dialog's buttons, so I've ruled that out. Why does my DialogFragment still disappear after rotation? I'm all but pulling my hair out over this, it worked fine until sometime after I implemented a Navigation Drawer. Could that be a part of the problem?

EDIT: False alarm, I discovered that my answer wasn't the solution! The problem reappeared after I finished moving all of my Fragments and Activities away from using the Support Libraries.

I did discover that this problem only exists in Activities in which the content fragment has not been declared statically in the Activity's layout. That is, if I have a <FrameLayout> defined in XML and use fragmentManager.beginTransaction().replace(R.id.content_frame, frag, tag).commit(); to load a fragment, any DialogFragments launched in that activity fail to reload when the device has been rotated.

Here's a screen recording that demonstrates the issue: https://www.youtube.com/watch?v=psK0pzMn6oc

Community
  • 1
  • 1
IAmKale
  • 3,146
  • 1
  • 25
  • 46
  • Have you tried showing this using the [example pattern](http://developer.android.com/reference/android/app/DialogFragment.html)? That is, calling `dialog.show(fragmentTransaction, tag)` rather than `show(fragmentManager, tag)`. These do [slightly different things](https://android.googlesource.com/platform/frameworks/support/+/refs/heads/master/v4/java/android/support/v4/app/DialogFragment.java). – Adam S Mar 12 '14 at 19:04
  • Under the **Alert Dialog** section they show a custom DialogFragment the same way I'm doing it right now. I tried calling `show()` using a FragmentTransaction anyway but it didn't change anything. – IAmKale Mar 12 '14 at 20:14
  • Ah, they do indeed. Have you tried displaying just a simple "Hello World" dialog within your activity/fragment context and making sure that stays put after rotation? If that doesn't work (something like [this](https://gist.github.com/adamsp/851f6a3aa4cb14c4dc9d)) then there's perhaps a problem around restoring state somewhere else. – Adam S Mar 12 '14 at 20:26
  • @AdamS Huh, I just implemented your example dialog and it too disappears when the app is rotated. I guess this means the problem's not with the dialogs, but the Activity itself. – IAmKale Mar 12 '14 at 20:34
  • Whoa, I decided to try importing `android.app.DialogFragment` instead of `android.support.v4.app.DialogFragment` in your dialog and it stayed open during rotation! What could that mean? I've been using v4 libraries for the majority of my Fragments, I wonder if I should move everything away from that. – IAmKale Mar 12 '14 at 20:39
  • If you're supporting API 8/9/10, you'll need to use the support library DialogFragment (as fragments weren't introduced until API 11, obviously). The fact that a non-support DialogFragment stayed open though suggests maybe you have an incorrect import somewhere? Other options are checking that your state restoration makes sense in your activity, and updating your v4 support library. – Adam S Mar 12 '14 at 20:43
  • 1
    I currently support APK 14 and up, so I think (for sake of my sanity) I'm going to go through my code and migrate as much as I can away from the v4 support libraries. – IAmKale Mar 12 '14 at 20:55
  • remove setRetainInstance(true) if your using it. dialogfragments can surive a rotation without it. – j2emanue Mar 12 '14 at 23:32
  • I don't use that anywhere in my code, I just double-checked. – IAmKale Mar 12 '14 at 23:37

1 Answers1

0

After some experimentation I discovered a solution. The Activity that launches the dialog needs to extend android.support.v4.app.FragmentActivity, and the DialogFragment needs to extend android.support.v4.app.DialogFragment.

Then, getSupportFragmentManager() must be called when launching the DialogFragment:

CustomDialog dialog = CustomDialog.newInstance();
dialog.show(getSupportFragmentManager(), "customDialog");

This should retain the dialog during rotation. There was no need to use setRetainInstance(true) in the dialog itself.

Mind you, this only works in instances in which an FragmentActivity calls a DialogFragment. I'm still trying to suss out a way to preserve a dialog that gets called via a Fragment instead.

IAmKale
  • 3,146
  • 1
  • 25
  • 46