Tom anMoney
Tom anMoney

Reputation: 1231

DialogFragment displayed from onContextItemSelected doesn't survive onPause/onResume

I have a DialogDragment which I can show one of two ways:

1) By tapping on a ListView item from its OnItemClickListener

2) By activating a the ListView's context menu and selecting a menu item

Doing #1 works fine under all lifecycle events, but if I invoke it via #2 and I pause the activity (by going Home) and the resuming it via the task switcher, the dialog is no longer displayed. The fragment is there, and I can rotate the device and show the dialog.

I experimented, and if I put the showing of the DialogFragment into a Handler with a delay of at least 1/2 seconds, it works.

The following snippet fails -- it shows the dialog, but then pause/resume hides it:

public boolean onContextItemSelected(android.view.MenuItem item) {
    boolean consumed = false;

    switch (item.getItemId()) {
    case R.id.menu_item:
        showMyDialogFragment();
        consumed = true;
        break;
    }

    return consumed;
}

So the following snippet works. Pause/resume display the dialog again correctly:

public boolean onContextItemSelected(android.view.MenuItem item) {
    boolean consumed = false;

    switch (item.getItemId()) {
    case R.id.menu_item:
        new Handler().postDelayed(new Runnable() {
            public void run() {
                showMyDialogFragment();
            }
        }, 300);

        consumed = true;
        break;
    }

    return consumed;
}

Replacing the 300ms second delay with a 0ms or 250ms delay causes it to be broken again. This repeatable 100% of the time.

This is a terrible hack obviously, made worse by the constant that's probably depends on the speed of the device.

Anybody know why this is going on and/or offer a better solution? I spent hours on this issue and this is the best I could come up with.

Upvotes: 8

Views: 1286

Answers (2)

CommonsWare
CommonsWare

Reputation: 1007474

I can reproduce this on Android 4.2 (ARM emulator and Galaxy Nexus). I am unable to reproduce your findings on an x86 4.1 emulator, a Nexus S (4.1), and a Motorola RAZR i (4.0). I can also reproduce the problem by modifying one of my own book samples. I filed an issue on it, using your sample: http://code.google.com/p/android/issues/detail?id=41901 Please add any other information you think would help them diagnose the problem.

With respect to a workaround, if 300ms works, then we have one of those lovely "timing issues", and I haven't the foggiest idea how you'd work around it, short of not using a menu to display it. For example, with your sample app, simply switching to SHOW_AS_ACTION_ALWAYS (and therefore having it be an item on the action bar rather than in an overflow menu) is sufficient to have the DialogFragment behave properly. Hopefully, you'll have a way of adjusting your UI to compensate for this bug, or perhaps somebody will cook up another workaround and post it here or on the issue.

Upvotes: 4

Roy Hinkley
Roy Hinkley

Reputation: 10641

I would recommend destroying the dialog on all pauses and recreate in onResume depending on state regardless of how the dialog is invoked. To do otherwise risks a memory leak if the app is killed by the OS in while paused.

To explicitly answer your question, don't rely on the OS to maintain your app state.

Upvotes: 2

Related Questions