Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dismissed dialog fragment reappears again when app is resumed

Hi I am developing an app that uses maps.

I am using Fragment Activity and a fragment named Fragment-A.

In Fragment-A there is a button, on clicking that button a Dialog Fragment pops up, displays a map with some location received previously from server.

Let us say this dialog fragment is DialogFragment-B.

It has a button to close, a button to navigate to google maps app to get directions.

If user navigate to DialogFragment-B and returns back to the Fragment-A, by clicking close button every thing is working fine.

But if the user clicks on back button the existing dialog fragment will close normally and the app functions normally.

But if the user then pressed home button or received a phone call and onResume is called even though the DialogFragment-B is dismissed earlier, it reappears and pressing close crashes the app with a null pointer exception

Here is my code to open the DialogFragment-B.

FragmentManager fm = getFragmentManager();
    FragmentTransaction ft = fm.beginTransaction();
    android.app.Fragment prev = fm.findFragmentByTag(MY_MAP);
    if (prev != null) {
        ft.remove(prev);
    }
    MyMapFragmentDialog newFragment = MyMapFragmentDialog
            .newInstance(eachPost);
    newFragment.show(ft, MY_MAP);

In DialogFragment-B on clicking close button, I call MyMapFragmentDialog.this.dismiss();

Please if any one have encountered this issue and overcame, guide me through.

like image 912
Programming Pirate Avatar asked Dec 20 '14 12:12

Programming Pirate


2 Answers

I had the same issue and it was solved by making sure I call super.onDismiss(dialog) in the onDismiss method of my DialogFragment subclass.

like image 85
Kalina Avatar answered Nov 18 '22 19:11

Kalina


Update: The answer by Kalina is a more elegant and simple solution - as I figured out later!

I am facing the same issue in one of my apps, and not finding the answer anywhere, went through the source code of the DialogFragment class, which is available at:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/4.0.1_r1/android/app/DialogFragment.java#DialogFragment.onDismiss%28android.content.DialogInterface%29

and there, I found the probable reason written in a comment, within the source of onDismiss(DialogInterface dialog) method:

// Note: we need to use allowStateLoss, because the dialog
// dispatches this asynchronously so we can receive the call
// after the activity is paused.  Worst case, when the user comes
// back to the activity they see the dialog again.

What I understood from this is that dismissal is not saved to the instance state, and when the activity resumes, it promptly shows it again as part of the instance state restoration - assuming that the fragment was never dismissed. Being an asynchronous event, there is no safe way to commit the dismiss without risking a

java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState

exception and consequent crash, which is probably why the authors of the class chose to do it this way.

The solution that worked for me was to separately monitor the state of the DialogFragment, by:

  • Storing it in a Class variable (referred to here as 'dialog')
  • Overriding the onDismiss(DialogInterface dialog) method, and
  • Setting a boolean dialogDismissed flag to true

-

@Override
public void onDismiss(DialogInterface dialog) {
   // dialogDismissed is a Class level variable in the containing Activity,
   // must be set to false each time the DialogFragment is shown
   dialogDismissed = true;
}
  • Note: if the DialogFragment is a separate Class, then then a method in the Activity will need to be called from the onDismiss to do this, perhaps by setting up an Interface

  • This flag must then be checked in the activity onResume() and a dismiss forced (after checking that the dialog is not null):

-

@Override
public void onResume() {
super.onResume();
//...
if (dialogDismissed && dialog != null) {
        dialog.dismiss();
    }    
}
like image 3
Mohan Noone Avatar answered Nov 18 '22 20:11

Mohan Noone