I don't use managed dialogs at all -- not only don't they work in
certain cases (like in a TabActivity), I think the whole system of
having to maintain global dialog ids is a pain. In my very large app,
I ended up with a DialogIds global enum, which I hated. I still have
the same issue with request ids for startActivityForResult(), but I
don't have a solution for that yet.
Here's an example of what I do, a simple MessageDialog class. It took
me a while to perfect the mechanism, but it works great with screen
orientation changes and activity save/restore. Also, I am purposely
not saving a reference to Context, to avoid any possible leaks. The
interesting part is how a new Listener is passed in to restoreState as
the listener is the only state that cannot be recrated reliably (the
target can be a different object if the Activity was destroyed/
resumed)
public class MessageDialog
{
public enum MessageDialogButton
{
POSITIVE,
NEGATIVE,
NEUTRAL
}
private static final String KEY_DIALOG_SHOWING =
"_dialog_showing"; //$NON-NLS-1$
private static final String KEY_DIALOG_DATA =
"_dialog_data"; //$NON-NLS-1$
private static final String KEY_TITLE =
"_title"; //$NON-NLS-1$
private static final String KEY_MESSAGE =
"_message"; //$NON-NLS-1$
private static final String KEY_ICON =
"_icon"; //$NON-NLS-1$
private static final String KEY_POSITIVE_BUTTON_TEXT =
"_positive_button_text"; //$NON-NLS-1$
private static final String KEY_NEGATIVE_BUTTON_TEXT =
"_negative_button_text"; //$NON-NLS-1$
private static final String KEY_NEUTRAL_BUTTON_TEXT =
"_neutral_button_text"; //$NON-NLS-1$
protected CharSequence baseKey;
Dialog dialog;
MessageDialogListener listener;
private CharSequence title;
private CharSequence message;
private int icon;
private CharSequence positiveButtonText;
private CharSequence negativeButtonText;
private CharSequence neutralButtonText;
public MessageDialog(CharSequence tag)
{
this.baseKey = this.getClass().getName() + '_' + tag;
}
public void saveState(Bundle bundle)
{
boolean dialogShowing = isShowing();
bundle.putBoolean(this.baseKey + KEY_DIALOG_SHOWING,
dialogShowing);
if (dialogShowing)
{
bundle.putBundle(this.baseKey + KEY_DIALOG_DATA,
this.dialog.onSaveInstanceState());
bundle.putCharSequence(this.baseKey + KEY_TITLE,
this.title);
bundle.putCharSequence(this.baseKey + KEY_MESSAGE,
this.message);
bundle.putInt(this.baseKey + KEY_ICON, this.icon);
bundle.putCharSequence(this.baseKey +
KEY_POSITIVE_BUTTON_TEXT, this.positiveButtonText);
bundle.putCharSequence(this.baseKey +
KEY_NEGATIVE_BUTTON_TEXT, this.negativeButtonText);
bundle.putCharSequence(this.baseKey +
KEY_NEUTRAL_BUTTON_TEXT, this.neutralButtonText);
}
}
public void restoreState(Context context, MessageDialogListener
_listener, Bundle bundle)
{
this.listener = _listener;
boolean dialogShowing = bundle.getBoolean(this.baseKey +
KEY_DIALOG_SHOWING);
if (dialogShowing)
{
this.title = bundle.getCharSequence(this.baseKey +
KEY_TITLE);
this.message = bundle.getCharSequence(this.baseKey +
KEY_MESSAGE);
this.icon = bundle.getInt(this.baseKey + KEY_ICON);
this.positiveButtonText =
bundle.getCharSequence(this.baseKey + KEY_POSITIVE_BUTTON_TEXT);
this.negativeButtonText =
bundle.getCharSequence(this.baseKey + KEY_NEGATIVE_BUTTON_TEXT);
this.neutralButtonText =
bundle.getCharSequence(this.baseKey + KEY_NEUTRAL_BUTTON_TEXT);
showDialog(context, checked);
Bundle dialogData = bundle.getBundle(this.baseKey +
KEY_DIALOG_DATA);
this.dialog.onRestoreInstanceState(dialogData);
}
}
public void show(Context context, MessageDialogListener _listener,
CharSequence _title, CharSequence _message, int _icon, CharSequence
_positiveButtonText, CharSequence _negativeButtonText, CharSequence
_neutralButtonText)
{
this.listener = _listener;
this.title = _title;
this.message = _message;
this.icon = _icon;
this.positiveButtonText = _positiveButtonText;
this.negativeButtonText = _negativeButtonText;
this.neutralButtonText = _neutralButtonText;
showDialog(context);
}
public void dismissIfShowing()
{
if (isShowing())
this.dialog.dismiss();
this.listener = null;
}
protected void showDialog(Context context)
{
Builder builder = new Builder(context);
builder.setTitle(this.title);
builder.setCancelable(false);
builder.setView(bodyView);
builder.setMessage(this.message);
if (this.icon != 0)
builder.setIcon(this.icon);
if (this.positiveButtonText != null)
builder.setPositiveButton(this.positiveButtonText, new
OnClickListener()
{
public void onClick(DialogInterface _dialog, int
which)
{
// Mark it not showing, no need to call .dismiss()
as it has been done already by AlertDialog
MessageDialog.this.dialog = null;
if (MessageDialog.this.listener != null)
MessageDialog.this.listener.onClose(MessageDialog.this,
MessageDialogButton.POSITIVE);
}
});
if (this.negativeButtonText != null)
builder.setNegativeButton(this.negativeButtonText, new
OnClickListener()
{
public void onClick(DialogInterface _dialog, int
which)
{
MessageDialog.this.dialog = null;
if (MessageDialog.this.listener != null)
MessageDialog.this.listener.onClose(MessageDialog.this,
MessageDialogButton.NEGATIVE);
}
});
if (this.neutralButtonText != null)
builder.setNeutralButton(this.neutralButtonText, new
OnClickListener()
{
public void onClick(DialogInterface _dialog, int
which)
{
MessageDialog.this.dialog = null;
if (MessageDialog.this.listener != null)
MessageDialog.this.listener.onClose(MessageDialog.this,
MessageDialogButton.NEUTRAL);
}
});
this.dialog = builder.show();
}
protected boolean isShowing()
{
return (this.dialog != null);
}
public interface MessageDialogListener
{
void onClose(MessageDialog dialog, MessageDialogButton
button);
}
}
Then your Activity would look something like this:
public class MyActivity extends Activity
{
private MessageDialog myDialog = new MessageDialog("myDialog");
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if (savedInstanceState != null)
this.myDialog.restoreState(this, createMyDialogListener(),
savedInstanceState);
}
protected void onDestroy()
{
super.onDestroy();
this.myDialog.dismissIfShowing();
}
protected void onSaveInstanceState(Bundle outState)
{
super.onSaveInstanceState(outState);
this.myDialog.saveState(outState);
}
private void showMyDialog()
{
this.myDialog.show(this, createMyDialogListener(),
"Message title", "Message to show", 0, "Ok", "Cancel", null);
}
private MessageDialogListener createMyDialogListener()
{
return new MessageDialogListener()
{
public void onClose(MessageDialog dialog,
MessageDialogButton button)
{
if (button == MessageDialogButton.POSITIVE)
doOk();
else
doCancel();
}
};
}
}
On Jun 25, 11:58 pm, TreKing <[email protected]> wrote:
> On Wed, Jun 23, 2010 at 8:02 AM, Surfer <[email protected]> wrote:
> > Hi, built a simple app that displays an alertDialog with two buttons.
> > The problem is it's not getting dismissed when i change orientation.
> > After change i get a leak warning on debugger and the dialog appears
> > twice(pressing back hides the first dialog, only a second back
> > dismisses it completely). Any ideas?
>
> OnCreate makes dialog #1 which is managed by the activity. So far so good.
>
> You rotate, forcing onCreate to get called again which creates a new dialog,
> #2.
>
> Meanwhile dialog #1 is being managed for you and is being re-shown. Now you
> have 2 dialogs.
>
> Since they have the same ID, the second is probably overriding the first in
> the Activity's management system causing a leak of the first.
>
> Simple fix: check if you Bundle is null in onCreate. If it is, you're a
> fresh start and can show a dialog for the first time. If it's not, you're
> being recreated and your managed dialog will show on it's own, so you don't
> have to do anything.
>
> -------------------------------------------------------------------------------------------------
> TreKing - Chicago transit tracking app for Android-powered
> deviceshttp://sites.google.com/site/rezmobileapps/treking
--
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en