
5.2 Application Context的创建过程
我们通过调用getApplicationContext来获取应用程序全局的Application Context,那么Application Context是如何创建的呢?在一个应用程序启动完成后,应用程序就会有一个全局的Application Context,那么我们就从应用程序启动过程开始着手。Application Context的创建过程的时序图如图5-2所示。

图5-2 Application Context的创建过程的时序图
ActivityThread 类作为应用程序进程的主线程管理类,它会调用它的内部类ApplicationThread的scheduleLaunchActivity方法来启动Activity,如下所示:

在ApplicationThread的scheduleLaunchActivity方法中向H类发送LAUNCH_ACTIVITY类型的消息,目的是将启动Activity的逻辑放在主线程的消息队列中,这样启动Activity的逻辑会在主线程中执行。我们接着查看H类的handleMessage方法对LAUNCH_ACTIVITY类型的消息的处理:


H继承自Handler,是ActivityThread的内部类。在注释1处通过getPackageInfoNoCheck方法获得LoadedApk 类型的对象,并将该对象赋值给ActivityClientRecord的成员变量packageInfo,其中LoadedApk用来描述已加载的APK文件。在注释2处调用了ActivityThread的handleLaunchActivity方法,如下所示:

在handleLaunchActivity方法中调用了ActivityThread的performLaunchActivity方法:

在performLaunchActivity方法中有很多重要的逻辑,这里只保留了和Application Context相关的逻辑,想要了解更多performLaunchActivity方法中的逻辑请查看4.1.3节的内容。ActivityClientRecord的成员变量packageInfo是LoadedApk类型的,我们接着来查看LoadedApk的makeApplication方法,如下所示:


在注释1处如果mApplication不为null则返回mApplication,这里假设是第一次启动应用程序,因此mApplication为null。在注释2处通过ContextImpl的createAppContext方法来创建ContextImpl。注释3处的代码用来创建Application,在Instrumentation的newApplication方法中传入了ClassLoader类型的对象以及注释2处创建的ContextImpl。在注释4处将Application赋值给ContextImpl的Context类型的成员变量mOuterContext,这样ContextImpl中也包含了Application的引用。在注释5处将Application赋值给LoadedApk的成员变量mApplication,这个mApplication是Application 类型的对象,它用来代表Application Context,在Application Context的获取过程中我们会再次提到mApplication。下面来查看注释3处的Application是如何创建的,Instrumentation的newApplication方法如下所示:

Instrumentation中有两个newApplication重载方法,最终会调用上面这个重载方法。注释1处通过反射来创建Application,并调用了Application的attach方法,将ContextImpl传进去,最后返回该Application,Application的attach方法如下所示:

在attach方法中调用了attachBaseContext方法,它在Application的父类ContextWrapper中实现,代码如下所示:

这个base一路传递过来指的是ContextImpl,它是Context的实现类,将ContextImpl赋值给ContextWrapper的Context类型的成员变量mBase,这样在ContextWrapper中就可以使用Context的方法,而Application继承自ContextWrapper,同样可以使用Context的方法。Application的attach方法的作用就是使Application可以使用Context的方法,这样Application才可以用来代表Application Context。
Application Context的创建过程就讲到这里,接下来我们来学习Application Context的获取过程。