Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 783
Tom anMoney Avatar asked Dec 24 '12 01:12

Tom anMoney


People also ask

How do you pass arguments to DialogFragment?

you can set your args. class IntervModifFragment : DialogFragment(), ModContract. View { companion object { fun newInstance( plom:String,type:String,position: Int):IntervModifFragment { val fragment =IntervModifFragment() val args = Bundle() args. putString( "1",plom) args.


2 Answers

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.

like image 71
CommonsWare Avatar answered Sep 23 '22 18:09

CommonsWare


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.

like image 25
Roy Hinkley Avatar answered Sep 23 '22 18:09

Roy Hinkley