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
Related
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()
I need to show a yes/no dialog in AsyncTask.onPostExecute() but I keep getting
java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState
when the screen is rotated just before the dialog is shown. I had a similar problem showing dialogs in the onActivityResult but have since moved the dialogs to the
onPostResume() as suggested by other posts but I am unable to solve this one.
Is it possible to show a yes/no dialog in the onpostexecute() without causing exception and without using "commitAllowingStateLoss"?
Your help is much appreciated.
I think you should maintain state of your activity in which you are calling the dialog, because every time when activities orientation changes onCreate() function calls and if you are initiating any AsyncTask in it, then it will execute it again. May be that's why you are facing the problem. Just maintain its state and then check it, hope it will help you.
Just add this code in your manifest file for that activity. Just type landscape or portrait according to your need.
android:screenOrientation="portrait/landscape"
Thank you.
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.
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().
I have created a custom dialog called MyCustomDialog which extends Dialog. I create and show my custom dialog as follows:
new MyCustomDialog(myContext).show();
I override the Dialog.onCreate(Bundle savedInstanceState) method to do my initialisation. I also check in this method whether a certain condition holds and, if not, I would like to dismiss/cancel my dialog. I have tried calling the cancel() and dismiss() methods in my dialog's onCreate(Bundle savedInstanceState) and onStart() methods but it has no effect.
Anyone know how to cancel or dismiss a dialog (from within the dialog) before it shows?
You should place the logic to determine if the dialog is to be shown outside of the onCreate() method. it does not belong there.
Alternatively, rename your show() method showIfRequired() (or something), and add the conditional show logic there.
I know this doesn't technically answer your question, but what you are trying to do is not the correct design. That's a good thing, as doing in the right way is actually simpler.
Also, as a side note, you should using DialogFragment in favor of Dialog. it's available in the v4 support library.
This is for API levels 10 and below:
First you should override onCreateDialog(int id, Bundle args) in the Activity class, is that what you're doing? Dialogs are always created and displayed as part of the Activity. Second, I don't think you can cancel/dismiss a dialog in onCreateDialog because it hasn't actually been created when onCreateDialog is called. That is, you can't cancel/dismiss something that hasn't been created. What you can try is to override onPrepareDialog() instead and do your check to cancel/dismiss the dialog there. At that point the dialog should actually have been created (just not displayed), so you would be able to prevent it from getting displayed if you call cancel/dismiss there.
onPrepareDialog() is the proper place to do any sort of checks and decision making on the dialog that is about to be displayed. This is for APIs prior to Honeycomb.
This is for APIs 11 and later:
If you are using a later API, you should extend DialogFragment instead. In this case I think you can handle the decision making in onCreateView() method of DialogFragment which is similar to onPrepareDialog().
I hope you've read through this:
http://developer.android.com/guide/topics/ui/dialogs.html
or this, depending on your API:
http://developer.android.com/reference/android/app/DialogFragment.html
Overall, perhaps a cleaner solution is to disable the button or mechanism that causes the dialog to show up in the first place? That is, write you code such that Dialog.show() is called only when it really needs to be called. I'd have to know more details about what exactly you're trying to do. For example, say you call Dialog.show() from the onClickListener of a button. you don't really want the user to press a button, expect a dialog, but have it not show up due to some reason the user doesn't understand. A better solution would be to disable the button all together so that it's obvious to the user that this function isn't available due to something else in the application.