Dialog的简单补充说明

在博客《AlertDialog创建过程详解》这篇博客中详细的说了Alert的创建过程,本篇博文就对Dialog的使用的知识点做其他的补充,闲言少叙,书归正传。

1.Dialog的关闭是线程安全的。

我们在关闭Dialog的时候是调用dismiss方法来关闭的,这个方法是线程安全的,通过该方法的实现上也可以体现出来:

private final Handler mHandler = new Handler();

private final Runnable mDismissAction = new Runnable() {
        public void run() {
            dismissDialog();
        }
    };
public void dismiss() {
       //如果不是在UI线程中
       if (Thread.currentThread() != mUiThread) {
            mHandler.post(mDismissAction);
        } else {
            mDismissAction.run();
        }
    }

该方法很简单,Dialog用一个全局变量mUiThread来存储UI线程,该变量在初始化Dialog的时候在Dialog的构造器中完成了初始化。

Dialog(Context context, int theme, boolean createContextWrapper) {
        //获取当前线程,也就是uiThrad
        mUiThread = Thread.currentThread();
        //处理Dialog show canncel dismiss的Handler
         mListenersHandler = new ListenersHandler(this);
    }
如果是非UI线程就通过Handler的post方法将mDismissAction这个Runnable传到Handler内部Looper去处理,如果是在UI线程中那么直接调用mDismissAction这个Ruannable对象的run方法(此时mDismissAction就是一个很普通的Java对象),效果跟是直接调用dismissDialog一样。

所以在我们在使用Dialog或者AlertDialog调用dismiss关闭Dialog的时候,下面的两种方式都是可以的,使用哪一个就看你自己的业务逻辑了:

new Thread() {
					public void run() {
						dialog.dismiss();
					}
				}.start();
				
或者
dialog.dismiss()//此时位于UI线程中
在关闭DiaoLog的时候,是调用dismissDialog这个方法来处理的:

  private void dismissDialog() {
        if (mDecor == null || !mShowing) {
            return;
        }
        //实际上是从mWindowManager中删除这个mDecor
        try {
            mWindowManager.removeView(mDecor);
        } finally {
            mDecor = null;
            mWindow.closeAllPanels();
            onStop();
            mShowing = false;
            //发送一个消息,在关闭Dialog的时候可以让用户做一些其他的操作。
            sendDismissMessage();
        }
    }
实际上关闭Dialog的核心原理很简单,跟关闭PopupWindow的原理一样(详见《 关于PopupWindow的简单说明》);事实上如果读者留心注意的话,会发现android实现的悬浮框等只要是有WindowManager的地方,关闭窗口的操作实际上调用的就是WindowManager的removeView操作(关于WidnowManager,详见《 WIndowMangaer杂谈》);

2.Dialog显示和关闭时的处理操作

在《AlertDialog创建过程详解》总我们知道在调用show方法显示出来Dialog界面的时候调用sendShowMessage();   方法发送一个消息;而关闭Dialog的时候又调用sendDismissMessage();发用了一个关闭界面的消息,正因为这两个消息的存在所以我们可以在Dialog刚显示或者关闭的时候做一些额外的操作,在代码中的体现如下:

//Dialog显示的时候调用,该方法内部会初始化Dialog的mShowMessage 这个变量,稍后会说明
		dialog.setOnShowListener(new OnShowListener() {
			@Override
			public void onShow(DialogInterface dialog) {
				Log.e("DialogTest","show Dialog,when the dialog is visialble,you can invoke this method to do something");
			}
		});
		//Dialog关闭的时候调用
		dialog.setOnDismissListener(new OnDismissListener() {
			@Override
			public void onDismiss(DialogInterface dialog) {
				Log.e("DialogTest","close Dialog,when you dimiss the dialog ,you can invoke this method to do something");
			}
		});
关于这两个方法具体怎么回调的,下面只挑 sendShowMessage方法来说明,sendDismissMessage方法的处理跟sendShowMessage方法类似就不在赘述。

  private void sendShowMessage() {
        if (mShowMessage != null) {
            Message.obtain(mShowMessage).sendToTarget();
        }
    }
mShowMessage 这个Message类型的变量在你调用setOnShowListener的时候做了初始化:

  public void setOnShowListener(OnShowListener listener) {
        if (listener != null) {
            mShowMessage = mListenersHandler.obtainMessage(SHOW, listener);
        } else {
            mShowMessage = null;
        }
    }

mShowMessage这个Message绑定了OnShowListener这个对象,该Message的what变量为SHOW这个int值,当调用sendShowMessage方法的发送消息的时候消息会在mListenersHandler这个Handler中进行处理。该Handler同mUiThread一样也是在Dialog的构造器中初始化的。所以接下来看看这个Handler的hanleMessage方法都做了些什么:

 private static final class ListenersHandler extends Handler {
        private WeakReference mDialog;

        public ListenersHandler(Dialog dialog) {
            mDialog = new WeakReference(dialog);
        }

        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                //此处省略了DIMISS,CANCLE两个case支线
                case SHOW:
                    ((OnShowListener) msg.obj).onShow(mDialog.get());
                    break;
            }
        }
    }
在看到这个方法之前,你可能会想到这个方法的内部的逻辑。很简单,就是简单的回调调用了你在程序中设置的OnShowListener的onShow方法。该方法的参数从该handler的初始化中可以看出来,指的是Dialog本身。

本篇博文就先到此位置吧,以后遇到Dialog的其余知识点还会补充,发现自己写博客的时候总喜欢引用一下自己以前写的博客链接,不知道是好是坏,但是有一点可以肯定的是android的知识点看起来很碎很凌乱,但是大体上的脉络还是很清晰的,借助查阅资料和查看源码,一点点积累总能不断的收获。





你可能感兴趣的:(android)