Alertdialog
The following is a self-asked question...
1. How to Create a window?
2. How do I handle messages such as ondismisslistener, oncancellistener, onshowlistener, and onkeylistener?
Self-summary:
Window Creation Process
Generally, when you call alertdialog DLG = new alertdialog (context );
Finally, create a window in the dialog class constructor. The Code is as follows:
Dialog(Context context, int theme, boolean createContextThemeWrapper) { if (createContextThemeWrapper) { if (theme == 0) { TypedValue outValue = new TypedValue(); context.getTheme().resolveAttribute(com.android.internal.R.attr.dialogTheme, outValue, true); theme = outValue.resourceId; } mContext = new ContextThemeWrapper(context, theme); } else { mContext = context; } mWindowManager = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE); Window w = PolicyManager.makeNewWindow(mContext); mWindow = w; w.setCallback(this); w.setWindowManager(mWindowManager, null, null); w.setGravity(Gravity.CENTER); mListenersHandler = new ListenersHandler(this); }
When we call
setOnShowListener(new OnShowListener() {@Overridepublic void onShow(DialogInterface dialog) {// TODO Auto-generated method stub}});
Internal implementation:
public void setOnShowListener(OnShowListener listener) { if (listener != null) { mShowMessage = mListenersHandler.obtainMessage(SHOW, listener); } else { mShowMessage = null; } } public final Message obtainMessage(int what, Object obj) { return Message.obtain(this, what, obj); } public static Message obtain(Handler h, int what, Object obj) { Message m = obtain(); m.target = h; m.what = what; m.obj = obj; return m; }
In this case, mlistenerhandler obtains a show message and assigns it to mshowmessage. The target of mshowmessage is mlistenerhandler.
Then continue to call
DLG. show (); below are: public void show (){//... try {mwindowmanager. addview (mdecor, L); mshowing = true; sendshowmessage ();} finally {}}
private void sendShowMessage() { if (mShowMessage != null) { // Obtain a new message so this dialog can be re-used Message.obtain(mShowMessage).sendToTarget(); } }
No. mshowmessage has been assigned a value when we call setonshowlistener.
In this case, the handlemessage of mlistenerhandler receives the show message.
Let's take a look at the handlemessage processing function of listenerhandler:
private static final class ListenersHandler extends Handler { private WeakReference<DialogInterface> mDialog; public ListenersHandler(Dialog dialog) { mDialog = new WeakReference<DialogInterface>(dialog); } @Override public void handleMessage(Message msg) { switch (msg.what) { case DISMISS: ((OnDismissListener) msg.obj).onDismiss(mDialog.get()); break; case CANCEL: ((OnCancelListener) msg.obj).onCancel(mDialog.get()); break; case SHOW: ((OnShowListener) msg.obj).onShow(mDialog.get()); break; } } }
Call back to trigger the User-Defined listener...
Others such as dismiss and cancel are the same.
OK. The call process of dismiss, cancel, and show event listening of dialog is completed...
The following describes the calling process of the three buttons (button_positive, button_negative, and button_neutral) Unique to alertdialog.
Generally, we use the following code to set a button for alertdialog and the event listening interface.
Setbutton (dialoginterface. button_neutral, "neutral", new dialoginterface. onclicklistener () {@ override public void onclick (dialoginterface dialog, int which) {// todo auto-generated method stub log. D ("Java-hh", "alertdialog -- button_neutral click") ;}}); internal trace code: Public void setbutton (INT whichbutton, charsequence text, onclicklistener listener) {malert. setbutton (whichbutton, text, listener, nu Ll);} continue tracking: Public void setbutton (INT whichbutton, charsequence text, dialoginterface. onclicklistener listener, message MSG) {If (MSG = NULL & listener! = NULL) {MSG = mhandler. obtainmessage (whichbutton, listener);} switch (whichbutton) {Case dialoginterface. button_positive: mbuttonpositivetext = text; mbuttonpositivemessage = MSG; break; Case dialoginterface. button_negative: mbuttonnegativetext = text; mbuttonnegativemessage = MSG; break; Case dialoginterface. button_neutral: mbuttonneutraltext = text; mbuttonneutralmessage = MSG; break; default: Throw new illegalargumentexception ("button does not exist ");}}
Here there is also a handler. We get a message whose target is handler (the Message ID is whichbutton, that is, the button ID ),
Then, use the member variable mbuttonneutralmessage to save the message. But when will the message be called? Check the Code:
package com.android.internal.app;public class AlertController ... { // ...View.OnClickListener mButtonHandler = new View.OnClickListener() { public void onClick(View v) { Message m = null; if (v == mButtonPositive && mButtonPositiveMessage != null) { m = Message.obtain(mButtonPositiveMessage); } else if (v == mButtonNegative && mButtonNegativeMessage != null) { m = Message.obtain(mButtonNegativeMessage); } else if (v == mButtonNeutral && mButtonNeutralMessage != null) { m = Message.obtain(mButtonNeutralMessage); } if (m != null) { m.sendToTarget(); } // Post a message so we dismiss after the above handlers are executed mHandler.obtainMessage(ButtonHandler.MSG_DISMISS_DIALOG, mDialogInterface) .sendToTarget(); } };// ...}
It turns out that an mbuttonhandler has set the message processing functions of the three buttons at the beginning, and then checks whether the related message listening interfaces are set.
If the message is set, the message is directly triggered (
m.sendToTarget();
). Finally, msg_dismiss_dialog is sent to close alertdialog, Which is why both cancel, OK, and neutral can close alertdialog.
Next, let's look at the implementation of mhandler message processing functions:
mHandler = new ButtonHandler(di); private static final class ButtonHandler extends Handler { // Button clicks have Message.what as the BUTTON{1,2,3} constant private static final int MSG_DISMISS_DIALOG = 1; private WeakReference<DialogInterface> mDialog; public ButtonHandler(DialogInterface dialog) { mDialog = new WeakReference<DialogInterface>(dialog); } @Override public void handleMessage(Message msg) { switch (msg.what) { case DialogInterface.BUTTON_POSITIVE: case DialogInterface.BUTTON_NEGATIVE: case DialogInterface.BUTTON_NEUTRAL: ((DialogInterface.OnClickListener) msg.obj).onClick(mDialog.get(), msg.what); break; case MSG_DISMISS_DIALOG: ((DialogInterface) msg.obj).dismiss(); } } }
How is it? It is clear, three button messages, plus a dismiss message processing function that closes alertdialog.
You need to consider using weakreference in buttonhandler. I guess it is because of the following considerations:
The user clicked the OK button and handler has not yet processed it
case DialogInterface.BUTTON_POSITIVE:
In this case, the dialog has been disabled due to special circumstances. In this case, the mdialog is null ..