我们先来看一眼Context的类继承关系
可以看到,Activity 与 Service 都是context.
我们首先来说下ContextWrapper, 顾名思义 , wrapper 译为 "包裹", So~ ContextWrapper 只是对Context的一个包裹作用.
ContextThemeWrapper. 看Theme我们就可以知道它是与 主题相关的. 想到什么了 ? 没错,就是在AndroidManifest内为application 或activity 指定的 theme. 而Service 没有主题, 是运行在后台的. 所以Service直接继承了ContextWrapper, 而Activity 继承至 ContextThemeWrapper
而ContextImpl 真正实现了 Context 的所有函数. 其操作context时, 其实现都是来自ContextImpl. 由以上可以看出,有多少个Activity 和Service 就有多少个 Context.
关于Context的创建 .
通过书中得知 , Activity本质上是一个Context, Activity基于ContextWrapper类. 然而ContextWrapper必须为其指定真正的Context对象,而真正实现了Context类的是 ContextImpl. 所以我们要知道ContextImpl是如何被创建的.
程序都是由ActivityThread 开始的. 创建Context对象也是在该类中完成, 在ActivityThread类中一共有7处创建ContextImpl.
其中只有attach()方法 仅在 Framework进程(system_server)启动时调用,程序运行时不会调用.
关于Application的 Context :
程序第一次启动时, 会调用handleBindApplication()方法中, 该方法两处创建了ContextImpl.但是都在if(data.instrumentationName!=null)中, 一般都不会进入该条件中. 只有创建了Android Unit Test 才会进入(2.3)
在API 23中 进入到handleBindApplication()中
会先直接创建一个ContextImpl对象, 在往下走. 会执行到data.info.makeApplication 会在其内又创建一个ContextImpl,这里为什么会创建两个ContextImpl对象还没有研究...等下回再分析.
然后这个然而我们需要一个PackageInfo, 这个info 是从何而来 ? 把代码往上推点 可看到
由图可以看到. 调用getPackageInfoNoCheck方法 会返回一个data.info. 然而data是什么 ? data其实是一个AppBindData. 它从何而来 ?
当第一次运行程序时, AMS 通过IPC会调用ActivityThread 中的 bindApplication方法, 在其内会构建一个AppBindData
之后会发送消息 调用 handleBindApplication.
下面我们来看看Activity 的 Context创建
启动Activity时, AMS会通过IPC调用到 scheduleLaunchActivity()方法,
scheduleLaunchActivity 会根据传入参数 构造一个本地的ActivityRecode数据类, 如图所示
之后会利用H (Handler) 发送消息 后 执行handleLaunchActivity, 将ActivityRecord传入
在handleLaunchActivity内 会调用performLaunchActivity
在performLaunchActivity内会执行r.packageInfo,makeApplication 然后在其内创建ContextImpl.
关于Service 创建Context
启动Service 时,AMS会通过IPC调用 ActivityThread 的 scheduleCreateService()方法,会在其内构建一个CreateServiceData 本地数据
之后会调用handleCreateService
获取packageInfo
创建ContextImpl, 接着执行makeApplication
在makeApplication 又创建了一次ContextImpl, 同上面Application一样,还没有研究.. 以上就是Context, 以及ContextImpl的由来了.
Context之间的关系
由上面我们可以知道Application、Activity、Service创建Context 的步骤大体一样,不同之处在于 Application、Activity、Service 使用了不同的数据对象.
所以 Context个数 = Activity个数 +Service个数 +1;