How to safely dismiss DialogFragment in onstop()? - android

I need to dismiss DialogFragment in onStop() of an FragmentActivity if it is showing, this is what I did
if(mAlertDlg != null && mAlertDlg.getDialog() != null)
mAlertDlg.dismiss();
But I usually got IllegalStateException. So please tell me why that code is wrong and what is the correct way to dismiss DialogFragment in onStop()? Thank you.

You should use dialogFragment.dismissAllowingStateLoss(). As the documentation say for commitAllowingStateLoss():
"Like commit() but allows the commit to be executed after an
activity's state is saved. This is dangerous because the commit can be
lost if the activity needs to later be restored from its state, so
this should only be used for cases where it is okay for the UI state
to change unexpectedly on the user."
So for dismissAllowingStateLoss() is the same approach.

If you want to dismiss a DialogFragment in onStop(), you probably don't want to use a DialogFragment but a classic Dialog instead.
The reason why DialogFragment exists is to allow a dialog to be restored automatically when the Activity is re-created. If you dismiss it in onStop(), it will never be restored.
Also, if you use dismissAllowingStateLoss(), the dismiss transaction may not be recorded properly in onSaveInstanceState() (as the name says, a state loss may occur), and this will result in the dialog being restored when the activity is re-created, and obviously that's not what you want.

Try using dismissAllowingStateLoss() instead of dismiss().

Related

How to judge after onSaveInstanceState in Android Development?

sometimes, i will get a
java.lang.IllegalStateException Can not perform this action after
onSaveInstanceState
when i try to show a DialogFragment.
so now the question is how i can write a if statement to judge current state before i involve the show method like this?
if(!isAfterOnSaveInstanceState())
dialog.show(getSupportFragment(),"MY DIALOG");
because i notice that the DialogFragment own the method dismissAllowingStateLoss() but lack of a method to allow state loss when show, maybe the design of the DialogFragent want developers to judge before call show method.
Thanks in advance.
onSaveInstanceState(): If called, this method will occur before onStop(). There are no guarantees about whether it will occur before or after onPause().
you can check isFinishing() before show your DialogFragment
if(!isFinishing()) {
// your code goes here...
}
more detail:link-1,link-2,link-3

android - dialogfragment using commitAllowStateLoss

What are the effects of commiting a dialogfragment transaction with state loss in android: Since its just a simple error dialog im showing with an ok button to close it i dont think i need to worry about state loss.
in my DialogFragment subclass i've over rided the show class so that it commits to include state loss so that i dont get illegalstateException...
#Override
public void show(FragmentManager manager, String tag) {
FragmentTransaction ft = manager.beginTransaction();
ft.add(this, tag);
//its just dialogs so can we allow state loss to not trigger illegalStateExceptions
ft.commitAllowingStateLoss();
}
According to this Article
Originally you are trying to avoid this error (Caused by: java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState).
This error stems from the fact that these Bundle objects of the onSaveInstanceState() represent a snapshot of an Activity at the moment onSaveInstanceState() was called, and nothing more. That means when you call FragmentTransaction#commit() after onSaveInstanceState() is called, the transaction won't be remembered because it was never recorded as part of the Activity's state in the first place
You tried to work around that by using commitAllowingStateLoss(), let's discuss
the difference between calling commit() and commitAllowingStateLoss() is that the latter will not throw an exception if state loss occurs. Usually you don't want to use this method because it implies that there is a possibility that state loss could happen. The better solution, of course, is to write your application so that commit() is guaranteed to be called before the activity's state has been saved, as this will result in a better user experience. Unless the possibility of state loss can't be avoided, commitAllowingStateLoss() should not be used.
Surprised no one ever gave a simple correct answer. The transaction will be lost. Since in this case you are adding a dialog fragment, if the fragments have to be restored, the dialog will be gone.
Test this by going into the developer settings and check 'never keep activities' or something that sounds a lot like that. Then go to your app, get the dialog open and press Home. Then open the app again.

Correct way to show a DialogFragment at Activity#onResume()

I need to show a DialogFragment every time the user enter the Activity, so the best callback method would be onResume(). Thing is I can't just call DialogFragment#show() cause it will throw some IllegalStateException, so I did this:
#Override
protected void onResume() {
super.onResume();
if(!dialog.isVisible()) {
dialog.show(getSupportFragmentManager(), "login-dialog");
}
}
#Override
protected void onPause() {
super.onPause();
if(dialog.isVisible()) {
dialog.dismiss();
}
}
I'm getting:
java.lang.IllegalStateException: Fragment already added: LoginDialog{41fac3e0 #0 login-dialog}
I had exactly the same exception and message while trying to keep a DialogFragment visible and working between screen rotations (orientation change). Are your fragments from the support library?
In my case, I was using the support library and the call to dialog.show() was in the activity's onCreate(). What seems to have solved the problem was the workaround presented here:
https://stackoverflow.com/a/14016339/3577211
Which basically is putting setRetainInstance(true) in your DialogFragment's onCreate(). The second part, that is, overriding its onDestroy, was the only way I have managed to make the DialogFragment not go away during screen rotations (and come back when rotating again), even though they say the latest support library versions took care of that (perhaps I have a mess with the jars in here).
You did not state whether you get the exception always or it works only the first time the activity is created. But what I guess is happening is that dialog.show() is actually a wrapper for a getFragmentManager().add() call, which probably checks whether setRetainInstance is true for the dialog and if it is false, the DialogFragment instance is added again to the same FragmentManager instance, which throws that exception.
Yet another suggestion would be not to use onResume() for that; instead use onCreate() and onSaveInstanceState(Bundle outState) with some kind of flag, since that way you can save data across activity cycles (and unless your dialog is just a popup constant message, which is very annoying to have every time the user hits onResume(), you probably have some data to interact with the user that could be lost in unexpected situations).
change
!dialog.isVisible()
to
!dialog.isAdded()

AlertDialog.dismiss()?

I am new in android and I am learning from developer.android.com site. Then I came across to AlertDialog.dismiss() where in site it is written that
This method Dismiss dialog and remove it from the screen. This method can be
invoked safely from any thread. Note that you should not override this
method to do cleanup when the dialog is dismissed, instead implement
that in onStop().
But I did not understand the mean of this line-
Note that you should not override this method to do cleanup when the
dialog is dismissed, instead implement that in onStop()
what is the mean of above line?
`.
AlertDialog.dismiss() uses to dismiss the dialog if it's opened up as describe at developer site
Note that you should not override this method to do cleanup when the dialog is dismissed, instead implement that in onStop().
The above statement simply means that as we used to garbage collect object which is no more referenced in class and avail for garbage collect. They are simpling stating that the approach like avail for garbage collection also applies in here but there are eligible inside onStop() of Activity.
So better to use it as onStop() as it's the last call of Activity Life Cycle which can dismissed your alertdialog. If it incase is there on the screen without dismissal.

When should i dismiss dialogs?

I've done some reading about dialogs in Android and I have an open issue:
When I'm using the Activity's methods that handle the dialogs (such as: onCreateDialog(...)), should I or shouldn't I dismiss the dialog in the onPause()?
Or maybe I should dismiss it only if I retained it - made an Activity member variable that has a reference to this dialog?
I've found this answer: https://stackoverflow.com/a/2851833/501560 saying that I need to explicitly call the dismiss() method, but I've read some other resources saying that the Activity should handle it by itself...
Thanks.
Dismissing a Dialog
When you're ready to close your dialog, you can dismiss it by calling dismiss() on the Dialog object. If necessary, you can also call dismissDialog(int) from the Activity, which effectively calls dismiss() on the Dialog for you.
If you are using onCreateDialog(int) to manage the state of your dialogs (as discussed in the previous section), then every time your dialog is dismissed, the state of the Dialog object is retained by the Activity. If you decide that you will no longer need this object or it's important that the state is cleared, then you should call removeDialog(int). This will remove any internal references to the object and if the dialog is showing, it will dismiss it.
Using dismiss listeners
If you'd like your application to perform some procedures the moment that a dialog is dismissed, then you should attach an on-dismiss listener to your Dialog.
First define the DialogInterface.OnDismissListener interface. This interface has just one method, onDismiss(DialogInterface), which will be called when the dialog is dismissed. Then simply pass your OnDismissListener implementation to
setOnDismissListener().
However, note that dialogs can also be "cancelled." This is a special case that indicates the dialog was explicitly cancelled by the user. This will occur if the user presses the "back" button to close the dialog, or if the dialog explicitly calls cancel() (perhaps from a "Cancel" button in the dialog). When a dialog is cancelled, the OnDismissListener will still be notified, but if you'd like to be informed that the dialog was explicitly cancelled (and not dismissed normally), then you should register an
DialogInterface.OnCancelListener with setOnCancelListener().
You never have to dismiss the dialog if it's managed by the Activity.
The Activity will dismiss the dialog when it's destroyed. If the Activity is pause, Dialog doesn't have to be dismissed.
I thought dialogs are supposed to be dismissed in onStop() or onPause() in the Activity lifecycle.
https://developer.android.com/reference/android/app/Dialog.html#dismiss()

Categories

Resources