Read The Fucking Source Code
引言
- Context:最熟悉的陌生人。
-
全能小伙儿
:启动Activity、启动服务、注册/发送广播、获取ContentResolver、获取类加载器、获取资源、操作数据库。
源码版本(Android R — API 30)
整体概览
![](https://img.haomeiwen.com/i10866057/1524f77fc1d8a328.png)
1. 继承关系图
![](https://img.haomeiwen.com/i10866057/7bdd8da8bb57437a.png)
整体说明
【上下文能力】:对外交互能力(上面提到的全能小伙儿
)。
- Context:上下文能力统筹定义。
- ContextWrapper:核心组件基类,关联了ContextImpl,上下文能力执行中转端,最终交给ContextImpl执行。
- ContextImpl:上下文能力执行代理端(真正执行端)。
- ContextThemeWrapper:提供了主题能力,专门为Activity而生的。
- DecorContext:为DecorView而生,拥有主题能力,为了更好的分类与解耦(相对Activity)。
- ReceiverRestrictedWrapper:为BroadcastReceiver而生,阉割掉了绑定服务等能力。
2. 应用组件 关联 Context
2.1 Application
![](https://img.haomeiwen.com/i10866057/f369401879027c9a.png)
2.2 Activity
![](https://img.haomeiwen.com/i10866057/326b184527db724d.png)
2.3 Service
![](https://img.haomeiwen.com/i10866057/580319ec51770af1.png)
2.4 BroadcastReceiver
![](https://img.haomeiwen.com/i10866057/db391cca843fe5e8.png)
2.5 ContentProvider
![](https://img.haomeiwen.com/i10866057/bb0d91cba69300e3.png)
3. 核心方法说明
3.1 基础类 核心方法说明
![](https://img.haomeiwen.com/i10866057/6cbb0a024e861da3.png)
3.2 应用组件 核心方法说明
![](https://img.haomeiwen.com/i10866057/66a28136d8aef6d6.png)
4. 小结
4.1 独特的 Activity 启动
Activity 的 Context 可以直接 startActivity
,其他的Context需要加上 FLAG_ACTIVITY_NEW_TASK
flags才能使用。为什么?由于 Activity 管理 UI视图 的特殊性,Activity 接管了本该由 ContextImpl 代理类来实现的功能。所以同样的方法,在 Activity 端的处理和 ContextImpl 的处理是不一致的。
4.2 独特的 Activity 套娃
Activity 的 getBaseContext
居然是 ContextThemeWrapper,如果我们在 Activity中依然想使用 ContextImpl 的方法,举例:那么直接 getBaseContext().startActivity
,调用层次是:
- 获取 Context 引用:
getBaseContext
-> ContextThemeWrapper; - 继承关系,直接调用父类:
ContextThemeWrapper.startActivity
->ContextWrapper.startActivity
; - 调用 ContextImpl(mBase) 代理:
ContextWrapper.startActivity
->mbase.startActivity
。
对比Application的 getBaseContext().startActivity
,调用层次是:
- 获取 Context 引用:
getBaseContext
-> ContextImpl; - 调用 ContextImpl的
startActivity
。
4.3 被阉割的 BroadcastReceiver
Receiver 的 Context 不可以执行 bindService
操作。否则直接抛异常(源码就不放了)。
Receiver 的 Context 执行 registerReceiver
操作分情况处理。只有当 receiver == null
用于获取sticky广播, 允许使用。
4.4 getApplicationContext 差异
- Application:
getApplicationContext()
就是自己 Application; - Activity/Service:
getApplication()
和getApplicationContext()
都是 Application; - BroadcastReceiver:在 onReceive 的过程,使用
getBaseContext().getApplicationContext()
获取 Application; - ContentProvider:使用
getBaseContext().getApplicationContext()
获取 Application(当然有可能为空:Provider 在初始化不会创建 Application 对象,多个 Apk 运行在同一个进程的情况下,第二个 Apk 通过 Provider 初始化,则 Context 为空)。
网友评论