![Android进阶解密](https://wfqqreader-1252317822.image.myqcloud.com/cover/331/31186331/b_31186331.jpg)
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=1739225007-BB3fC7Zlx7p5UbyGybkLmtUK4Of0Onua-0-ec0fa099cabb0e36d0b5ca49e8e24421)
图5-3 Activity的Context创建过程的时序图
ActivityThread是应用程序进程的主线程管理类,它的内部类ApplicationThread会调用scheduleLaunchActivity方法来启动Activity,scheduleLaunchActivity方法如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer152.jpg?sign=1739225007-0j05uiOjW6yuypRgKrHS8z8r9xqCcGTw-0-e2d40bcbd60e965235722233fe68bdb7)
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=1739225007-XAhjCeiu7mTLSF5ikYbBgS88Hd0xmOda-0-1173baf75c44632bfe96b8e8ca337398)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer154.jpg?sign=1739225007-Wn7SVUdlpbmPekYjpSHFSL9SNda0btHT-0-e581b866c865fba8a267e95414a228a9)
在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=1739225007-XFqzC53bfXawMsismCq0EOHOGzzduvra-0-577c67fa9e7ed283001fc0e9e5f9c894)
在createBaseContextForActivity方法中会调用ContextImpl的createActivityContext方法来创建ContextImpl。我们回到ActivityThread的performLaunchActivity方法,查看注释4处的Activity的attach方法,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer156.jpg?sign=1739225007-l60VB3J88Bonsqs2DRs88g2jg7LLeWXg-0-6da2bdd7e383c6f1eecbb2a071460f57)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer157.jpg?sign=1739225007-GOxcuxxjlr312ci5TMTiueZNr0NGd1nQ-0-d0199935c4cb4ddfaf8a2cd073e793ed)
在注释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=1739225007-o4BZ9bsQxT9Ll05y73NfqGNmCJGc2SG5-0-552a34c5fd6c91518a88561507874dc2)
attachBaseContext 方法接着调用ContextThemeWrapper的父类ContextWrapper的attachBaseContext方法:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer159.jpg?sign=1739225007-XvFE0rDBShQjuGkaLvHRBRQfqeNy2Hcf-0-d18975871b35ee40dcc7d1fac0ef5c05)
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer160.jpg?sign=1739225007-YwSdO3d8Rg0P6SOfPiq25i9hqVWHIWFT-0-efe82400308fab2728593fce2a7ce30d)
注释1处的base指的是一路传递过来的Activity的ContextImpl,将它赋值给ContextWrapper的成员变量mBase。这样ContextWrapper的功能就可以交由ContextImpl来处理,举个例子,如下所示:
![](https://epubservercos.yuewen.com/D63A94/16896237205618706/epubprivate/OEBPS/Images/figer161.jpg?sign=1739225007-QyyNTDMUFfD2JXbiKhu0jCwpKPQpi3FX-0-0214f8f495051e52289c4ed887d57264)
当我们调用ContextWrapper的getTheme方法时,其实就是调用了ContextImpl的getTheme方法。Activity的Context创建过程就讲到这里。总结一下,在启动Activity的过程中创建ContextImpl,并赋值给ContextWrapper的成员变量mBase。Activity继承自ContextWrapper的子类ContextThemeWrapper,这样在Activity中就可以使用Context中定义的方法了。