Proper way of dismissing DialogFragment while application is in background

AndroidAndroid FragmentsAndroid DialogAndroid Dialogfragment

Android Problem Overview


I started using DialogFragment, because they are working nicely through orientation changes, and stuff. But there is nasty problem I encountered.

I have AsyncTask that shows progress DialogFragment and dismisses it onPostExecute. Everything works fine, except when onPostExecute happens while application is in background (after pressing Home button, for example). Then I got this error on DialogFragment dismissing - "Can not perform this action after onSaveInstanceState". Doh. Regular dialogs works just fine. But not FragmentDialog.

So I wonder, what is the proper way of dismissing DialogFragment while application is in background? I haven't really worked with Fragments a lot, so I think that I'm just missing something.

Android Solutions


Solution 1 - Android

DialogFragment has a method called dismissAllowingStateLoss()

Solution 2 - Android

This is what I did (df == dialogFragment):

Make sure that you call the dialog this way:

df.show(getFragmentManager(), "DialogFragment_FLAG");

When you want to dismis the dialog make this check:

if (df.isResumed()){
  df.dismiss();
}
return;

Make sure that you have the following in the onResume() method of your fragment (not df)

@Override
public void onResume(){
  Fragment f = getFragmentManager().findFragmentByTag("DialogFragment_FLAG");
  if (f != null) {
    DialogFragment df = (DialogFragment) f;
    df.dismiss();
  }
  super.onResume();
}   

This way, the dialog will be dismissed if it's visible.. if not visible the dialog is going to be dismisded next the fragment becomes visible (onResume)...

Solution 3 - Android

This is what I had to do to achieve what you want: I have a Fragment activity on which i was showing a dialog fragment named fragment_RedemptionPayment which is globally declared at the top. The following code dismisses the DialogFragment if it was showing before the activity goes in background and comes back in foreground.

     @Override
        public void onResume() {
            super.onResume();        
            if(fragment_RedemptionPayment.isVisible()){
                fragment_RedemptionPayment.dismiss();
            }
}

Solution 4 - Android

Another new way of checking the state before calling dismiss is this:

if(!dialog.isStateSaved){
    dialog.dismiss()
} else {
    //Change the UI to suit your functionality
}

In this way its is checked that state is saved or not, basically on pause and onSaveInstanceState has been called.

For Java you can use isStateSaved()

Solution 5 - Android

A solution that might work is setting Fragment.setRetainInstance(true) in your dialogfragment, but that's not the prettiest of fixes.

Sometimes I have noticed that I have to queue up my dialog actions to let the framework restore the state first. If you can get hold of the current Looper (Activity.getMainLooper()) and wrap that in a Handler you could try passing your dismissal to the back of the queue by posting a runnable on that queue.

I often end up using a separate fragment that it retaininstance(true) that has a ResultReceiver. So i pass on that result receiver to my jobs and handle callbacks in its onReceive (often as a router for other receivers). But that might be a bit more work than it is worth if you are using async tasks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSverView Question on Stackoverflow
Solution 1 - AndroidJiang QiView Answer on Stackoverflow
Solution 2 - AndroidMohammed AljarrahView Answer on Stackoverflow
Solution 3 - AndroidShahid SarwarView Answer on Stackoverflow
Solution 4 - AndroidKnowITView Answer on Stackoverflow
Solution 5 - AndroidSebastian OlssonView Answer on Stackoverflow