一直想搞明白Dialog到底是怎么创建的,今天有点时间,追踪一下Dialog的创建过程。由于能力有限,具体的实现细节不做分析,主要是搞懂代码调用的流程,从new Diaolg到Dialog显示的屏幕上的调用关系。以下便从Dialog的构造函数入手,开始一步步追踪Dialog的创建流程。
一.Dialog的构造函数
从构造函数出发,所有的构造函数都会调用下面这个构造函数:
public Dialog(Context context, int theme) {
this(context, theme, true);
}
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.setOnWindowDismissedCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
}
剔除不重要的,这里面只有两样东西特别重要,mWindowManger和mWindow。它们分别是窗口管理类和代表一个窗口的类。创建mWindow使用的是PolicyManager这个类,这个类在android api中并没有,是一个系统级别的类。所以想使用这个类创建一个window,然后自己去做一个Dialog是比较困难的。暂时不想这些,那么想想代表这个窗口的类(Window)是什么样的?mWindowManager又是怎么管理窗口的呢?带着问题,继续追踪代码。先看看mWindow到底是个什么东西。
二.Window和PhoneWindow
对于Window这个类,先看看它的注释:/**
* Abstract base class for a top-level window look and behavior policy. An
* instance of this class should be used as the top-level view added to the
* window manager. It provides standard UI policies such as a background, title
* area, default key processing, etc.
*
* <p>The only existing implementation of this abstract class is
* android.policy.PhoneWindow, which you should instantiate when needing a
* Window. Eventually that class will be refactored and a factory method
* added for creating Window instances without knowing about a particular
* implementation.
*/
这段话的意思是说:Window类是一个抽象顶层窗口外观和行为策略的抽象类。这个类的实例应该作为定层的view加入到window manager中.Window提供了标准的UI策略,比如背景,标题区域,默认的按键处理等等。
这个类的唯一实例就是PhoneWindow,当我们需要一个Window时,PhoneWindow应该被实例化。最终,这个类将会被重构,并且加入一个工厂方法,用来创建一个window的实例,这样就遮蔽了创建这个类的具体细节。
接下来看看PhoneWindow,这个Window的唯一实现类,是怎样实现UI的外观绘制与事件处理的。
下面是它的构造函数:
public PhoneWindow(Context context) {
super(context);
mLayoutInflater = LayoutInflater.from(context);
}
构造函数获得了一个LayoutInflater的实例,这个实例用于构造一个view,因此可以猜测PhoneWindow中肯定会构造某个view.
看完了构造函数该看什么了呢?这个类有很多很多函数,总不能通通看一遍吧?这个时候,没有思路了还得回过头看Dialog类,看它是怎么把一个Dialog显示出来的。
三.show()方法
想想我们是怎么使用Dilog的,一般创建一个Dilog对象,设置一堆东西,不管设置什么,最终要调用show()方法,不然Dialog就不会显示,所以,秘密似乎在show()方法中。
那么,show方法都做了什么呢?
/**
* Start the