最近读了深入理解Android卷I,了解了一些有关于Activity显示的知识,在此写下一篇博客总结。
有兴趣自己看Android源码的同学可以前往:
http://grepcode.com/project/repository.grepcode.com/java/ext/com.google.android/android/
本博客分析的Android版本为4.4
Activity的创建
要谈到Activity的界面显示,我们就得从Activity的创建说起
众所周知,Zygote是我们Android系统与应用启动相关的一个非常重要的进程:当我们要启动一个新的APP进程的时候,Zygote进程就会通过fork创建一个子进程,而子进程的入口函数就是ActivityThread类的main函数:
1 | public static void main(String[] args) { |
省略一些无关的代码,我们可以看到在main函数中ActivityThread进行了一些与Looper、Handler相关的初始化操作,初始化完成后就能使用handler来处理message了,我们来看一下能处理什么消息(ActivityThread类的handleMessage函数):
1 | public void handleMessage(Message msg) { |
能处理的message实在太多,此处我们只观察第一条。从message的信息来看,这条消息毫无疑问是用来创建一个Activity,我们再来看看第10行关键的handleLaunchActivity方法:
1 | private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) { |
这个函数中有两个关键的点:
- performLaunchActivity:创建一个Activity
- handleResumeActivity:为Activity界面显示进行准备
performLaunchActivity
我们先来分析第一个关键点(ActivityThread#performLaunchActivity):
1 | private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) { |
此处有三个关键的点:
- newActivity:创建Activity
- attach:对Activity执行一些初始化工作
- callActivityOnCreate:执行Activity的onCreate方法初始化
newActivity
第7行的newActivity方法创建了Activity,我们一起看一下这个方法究竟做了什么(android.app.Instrumentation#newActivity):
1 | public Activity newActivity(ClassLoader cl, String className, |
非常简单,newActivity方法通过Java的反射机制创建了Activity
attach
我们再回到performLaunchActivity方法继续往下看,第10行有一个非常关键的attach函数,我们来看一下(android.app.Activity#attach):
1 | final void attach(Context context, ActivityThread aThread, |
这里出现了两个非常关键的对象:Window和WindowManager
我们先来看一看Window的官方解释:
1 | 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. |
大致的意思是:WIndow是一个抽象基类,用于控制顶层窗口的外观与行为(即绘制背景和标题栏、默认的按键处理等)。它应该作为一个顶层的View加入到WindowManager中。
因此,View、Window和WindowManager的关系可以用下图来表示:
WindowManager拥有Window,而Window是UI的顶层View
那么由于Window是一个抽象类,在方法中它的实际类型是什么呢?我们一起回到代码中的第9行,此处调用了makeNewWindow方法来创建一个Window:
(com.android.internal.policy.PolicyManager)
1 | public final class PolicyManager { |
从第18行的方法可以看到,PolicyManager调用了sPolicy变量的makeNewWindow方法来返回一个Window对象。那么sPolicy是什么呢?从第10行和第2行我们可以看出这是一个由Java反射加载的类,我们继续去看sPolicy的makeNewWindow方法:
(com.android.internal.policy.impl.Policy)
1 | public Window makeNewWindow(Context context) { |
OK,看来我们的Window的实际对象是一个PhoneWindow。
我们回到attach方法中,继续看一下WindowManager是个什么鬼:
(android.app.Activity)
1 | final void attach(Context context, ActivityThread aThread, |
看到第17行的WindowManager与第12行的setWindowManager相关,由于mWindow的实际类型是PhoneWindow,我们来看一下他的setWindowManager方法:
(com.android.internal.policy.impl.PhoneWindow)
1 | public void setWindowManager(WindowManager wm, IBinder appToken, String appName, |
在第10行我们可以看到调用了createLocalWindowManager来生成一个WindowManager,该方法如下:
(android.view.WindowManagerImpl)
1 | public WindowManagerImpl createLocalWindowManager(Window parentWindow) { |
因此我们最终的WindowManager的实际类型是一个WindowManagerImpl。
此时,View、Window和WindowManager的关系图更新为如下所示:
OK,剩下的内容我们将在下一篇博客中继续分析,在此之前我们先来回顾一下本篇博客的分析路线:
上图中绿色的区域为我们分析完成的部分,现在我们经过以上步骤,获得了:Activity、Window和与Window绑定的WindowManger,下次我们将继续从callActivityOnCreate方法开始继续分析Activity的显示过程