Android - How to Dismiss All Dialogs in onPause

I have an activity that could show different dialogs during run-time. I use onCreateDialog(int id) to create each dialog and I use showDialog(int id) and dismissDialog(int id) method show and dismiss each dialog respectively.

When onPause() is called, I don't know which dialog (if any) is being displayed. I want to make sure that when onPause is called, all dialogs are dimissed. Is there a recommended way to dismiss all dialogs? Would I have to call dismissDialog() for each dialog?


If you are using DialogFragment and you want to dismiss all you can use:

/**
 * Dismiss all DialogFragments added to given FragmentManager and child fragments
 */
public static void dismissAllDialogs(FragmentManager manager) {
    List<Fragment> fragments = manager.getFragments();

    if (fragments == null)
        return;

    for (Fragment fragment : fragments) {
        if (fragment instanceof DialogFragment) {
            DialogFragment dialogFragment = (DialogFragment) fragment;
            dialogFragment.dismissAllowingStateLoss();
        }

        FragmentManager childFragmentManager = fragment.getChildFragmentManager();
        if (childFragmentManager != null)
            dismissAllDialogs(childFragmentManager);
    }
}

Depending on how many dialog's we're talking about. The short answer is yes, you'll have to dismiss each dialog.

There may be elegant ways of doing this other than simply having a few dialogs declared at the activity level. You could store all the dialogs in a HashMap once they are declared and then iterate through the list and close each one onPause.

Since you don't know which are open you'll need to go through and test or track the states.

However, if you truly have this many dialogs on your screen you may have some issues with your UI/UX design as Android should give you a model which makes it easy to implement it without what seems like poor design.


With android's recent emphasis on using DialogFragment container you wil not need to call dismiss on each

Since the dialogs will have a Fragment container you may simply use their lifecycle. Consider this DialogFragment:

public class FragDialog extends DialogFragment{

    public ProgressDialog _dialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            //this.dismiss();     <-- The dialogs may be dismissed here
        }
    }

    @Override
    public Dialog onCreateDialog(final Bundle savedInstanceState) {

        _dialog = new ProgressDialog(getActivity());
        return _dialog;
    }

    @Override
    public void onPause() {
        super.onPause();
        // <--------- You may overload onPause
    }
}

Which you will show in your activity using a fragmentmanager normally calling it like this:

FragmentManager fm = getSupportFragmentManager();
FragDialog fragDialog = new FragDialog();
fragDialog.show(fm, "my_tag");

Note that you may actually alter what the DialogFragment does in onPause. When your activity calls onPause, this onPause will be called too.

Dismissing the dialog in onPause() using this.dismiss() won't do the work because once the activity resumes it will resume the dialog as well. (I think this is because the savestate is stored prior to onPause).

But you can safely dismiss the dialog(s) in onCreate if you detect a savedInstanceState (a resume) like shown in the code.


I have a different solution, that could be good. You only have set your Custom Dialog extend to this SiblingDialog, that will subscribe your Dialog to a broadcast event of closing dialogs. So you may send the broadcast event anywhere you want and all the SiblingDialogs will be closed.

In this example the cancel and dismiss dialog method have been override so the SiblingDialog itself closes every other Sibling at close.

public class SiblingDialog extends Dialog {

    protected LocalBroadcastManager mLocalBroadcastManager;

    protected BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            switch (intent.getAction()) {
                case "CLOSE_ALL_DIALOGS":
                    if (isShowing()) {
                        dismiss();
                    }
                    break;
                default:
                    break;
            }
        }
    };
    String[] ACTIONS_LIST = {"CLOSE_ALL_DIALOGS"};

    public SiblingDialog(Context context) {
        super(context);
    }

    public SiblingDialog(Context context, int themeResId) {
        super(context, themeResId);
    }


    public SiblingDialog(Context context, boolean cancelable, OnCancelListener cancelListener) {
        super(context, cancelable, cancelListener);
    }

    private void registerTheBroadCast() {
        mLocalBroadcastManager = LocalBroadcastManager.getInstance(getContext());
        IntentFilter mIntentFilter = new IntentFilter();
        for (String actions : ACTIONS_LIST) {
            mIntentFilter.addAction(actions);
        }
        mLocalBroadcastManager.registerReceiver(mBroadcastReceiver, mIntentFilter);
    }

    private void unregisterBroadCast() {
        mLocalBroadcastManager.unregisterReceiver(mBroadcastReceiver);
    }

    @Override
    public void show() {
        registerTheBroadCast();
        super.show();
    }

    @Override
    public void cancel() {
        unregisterBroadCast();
        mLocalBroadcastManager.sendBroadcast(newIntent("CLOSE_ALL_DIALOGS"));
        super.cancel();

    }

    @Override
    public void dismiss() {
        unregisterBroadCast();
        mLocalBroadcastManager.sendBroadcast(new Intent("CLOSE_ALL_DIALOGS"));
        super.dismiss();
    }
}

In Kotlin you can make it much easier.

If your want to dismiss all DialogFragments:

    private fun dismissDialogs() {
        supportFragmentManager.fragments.takeIf { it.isNotEmpty() }
                ?.map { (it as? DialogFragment)?.dismiss() }
    }

If your want to dismiss all DialogFragments except one:

    private fun dismissDialogs(fragment: DialogFragment) {
        supportFragmentManager.fragments.takeIf { it.isNotEmpty() }
                ?.map { if (it != fragment) (it as? DialogFragment)?.dismiss() }
    }