- Android进阶解密
- 刘望舒
- 856字
- 2020-08-27 17:04:56
5.4 Activity的Context创建过程
想要在Activity中使用Context提供的方法,务必要先创建Context。Activity的Context会在Activity的启动过程中被创建,在4.1.3节中讲到了ActivityThread启动Activity的过程,我们就从这里开始分析。Activity的Context创建过程的时序图如图5-3所示。
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer151.jpg?sign=1739692064-Sd7rnbygbghdVVUKCrjlk112Bav2VJMb-0-a4a5a3dcabd9dc5191cb35e857263747)
图5-3 Activity的Context创建过程的时序图
ActivityThread是应用程序进程的主线程管理类,它的内部类ApplicationThread会调用scheduleLaunchActivity方法来启动Activity,scheduleLaunchActivity方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer152.jpg?sign=1739692064-qXDri16iI4ZPRJpye9nT3zfh9l9F0WcM-0-30f620d81aec8300baf6436ed91a029b)
scheduleLaunchActivity 方法将启动Activity的参数封装成ActivityClientRecord,sendMessage方法向H类发送类型为LAUNCH_ACTIVITY的消息,并将ActivityClientRecord传递过去。sendMessage方法的目的是将启动Activity的逻辑放在主线程的消息队列中,这样启动Activity的逻辑就会在主线程中执行。H类的handleMessage方法会对LAUNCH_ACTIVITY类型的消息进行处理,其中调用了ActivityThread的handleLaunchActivity方法,而在handleLaunchActivity方法中又调用了ActivityThread的performLaunchActivity方法,这一过程在5.2节已经讲过了,我们直接来查看ActivityThread的performLaunchActivity方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer153.jpg?sign=1739692064-biJzm7sewxhdtfySMz0il5vULMLwQxEf-0-1f33a22fa17b72169aac57167a4cd417)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer154.jpg?sign=1739692064-h2y0kl4Fqebvtj5otx2mkPXRhQ8SxYBW-0-7dcb23b874bed50a866d8af8765be188)
在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方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer155.jpg?sign=1739692064-R97NyyOFGcA7X6Zi74VP6jHns1a5LwD0-0-fb1002f7f1fc12fad906f87023817732)
在createBaseContextForActivity方法中会调用ContextImpl的createActivityContext方法来创建ContextImpl。我们回到ActivityThread的performLaunchActivity方法,查看注释4处的Activity的attach方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer156.jpg?sign=1739692064-OEizIuhJP2IzDVkhc6TYsaPT0qxqCpll-0-fe1fc270047b4bbda06299145040bde5)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer157.jpg?sign=1739692064-apdaDsGG9Ud41F4pTUkffTsKLSmBzTfG-0-e8a21d57c824609d58614342cab06cae)
在注释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中实现,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer158.jpg?sign=1739692064-eCw00uR5urxAk7D8zqk2a2V6DYWFN22v-0-04ebd759c466e9485815b01ff2654b92)
attachBaseContext 方法接着调用ContextThemeWrapper的父类ContextWrapper的attachBaseContext方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer159.jpg?sign=1739692064-EviokLM5n8npHmUVBUeOBG6Wd2Ze5btt-0-05ade1e3f41ff4f642db0e2c5c8cec63)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer160.jpg?sign=1739692064-WuZWy2VSiyKbTRVdPlOUMBUZj1x3xlQq-0-535de553f3b97f5ed6c6c0a33b71c930)
注释1处的base指的是一路传递过来的Activity的ContextImpl,将它赋值给ContextWrapper的成员变量mBase。这样ContextWrapper的功能就可以交由ContextImpl来处理,举个例子,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer161.jpg?sign=1739692064-eGCFRDqIpflP8bzBXrEu3jMJyUplPqEx-0-d6608f9d0635f7079c9bad846b7bf0dd)
当我们调用ContextWrapper的getTheme方法时,其实就是调用了ContextImpl的getTheme方法。Activity的Context创建过程就讲到这里。总结一下,在启动Activity的过程中创建ContextImpl,并赋值给ContextWrapper的成员变量mBase。Activity继承自ContextWrapper的子类ContextThemeWrapper,这样在Activity中就可以使用Context中定义的方法了。