5.4 Activity的Context创建过程
想要在Activity中使用Context提供的方法,务必要先创建Context。Activity的Context会在Activity的启动过程中被创建,在4.1.3节中讲到了ActivityThread启动Activity的过程,我们就从这里开始分析。Activity的Context创建过程的时序图如图5-3所示。
图5-3 Activity的Context创建过程的时序图
ActivityThread是应用程序进程的主线程管理类,它的内部类ApplicationThread会调用scheduleLaunchActivity方法来启动Activity,scheduleLaunchActivity方法如下所示:
scheduleLaunchActivity 方法将启动Activity的参数封装成ActivityClientRecord,sendMessage方法向H类发送类型为LAUNCH_ACTIVITY的消息,并将ActivityClientRecord传递过去。sendMessage方法的目的是将启动Activity的逻辑放在主线程的消息队列中,这样启动Activity的逻辑就会在主线程中执行。H类的handleMessage方法会对LAUNCH_ACTIVITY类型的消息进行处理,其中调用了ActivityThread的handleLaunchActivity方法,而在handleLaunchActivity方法中又调用了ActivityThread的performLaunchActivity方法,这一过程在5.2节已经讲过了,我们直接来查看ActivityThread的performLaunchActivity方法:
在performLaunchActivity方法中有很多重要的逻辑,这里只保留了Activity的Context相关的逻辑。在注释2处用来创建Activity的实例。在注释1处通过createBaseContextForActivity方法来创建Activity的ContextImpl,并将ContextImpl传入注释4处的activity的attach方法中。在注释3处调用了ContextImpl的setOuterContext方法,将此前创建的Activity实例赋值给ContextImpl的成员变量mOuterContext,这样ContextImpl也可以访问Activity的变量和方法。在注释5处m.Instrumentation的callActivityOnCreate方法中会调用Activity的onCreate方法。我们查看注释1处的createBaseContextForActivity方法:
在createBaseContextForActivity方法中会调用ContextImpl的createActivityContext方法来创建ContextImpl。我们回到ActivityThread的performLaunchActivity方法,查看注释4处的Activity的attach方法,如下所示:
在注释2处创建PhoneWindow,它代表应用程序窗口。PhoneWindow在运行中会间接触发很多事件,比如点击、菜单弹出、屏幕焦点变化等事件,这些事件需要转发给与PhoneWindow关联的Actvity,转发操作通过Window.Callback接口实现,Actvity实现了这个接口。在注释3处将当前Activity通过Window的setCallback方法传递给PhoneWindow。在注释4处为PhoneWindow设置WindowManager,在注释5处获取WindowManager并赋值给Activity的成员变量mWindowManager,这样在Activity中就可以通过getWindowManager方法来获取WindowManager。注释1处的attachBaseContext方法在ContextThemeWrapper中实现,如下所示:
attachBaseContext 方法接着调用ContextThemeWrapper的父类ContextWrapper的attachBaseContext方法:
注释1处的base指的是一路传递过来的Activity的ContextImpl,将它赋值给ContextWrapper的成员变量mBase。这样ContextWrapper的功能就可以交由ContextImpl来处理,举个例子,如下所示:
当我们调用ContextWrapper的getTheme方法时,其实就是调用了ContextImpl的getTheme方法。Activity的Context创建过程就讲到这里。总结一下,在启动Activity的过程中创建ContextImpl,并赋值给ContextWrapper的成员变量mBase。Activity继承自ContextWrapper的子类ContextThemeWrapper,这样在Activity中就可以使用Context中定义的方法了。