Context 对于开发人员实在太常见了,各种 API 调用都需要 Context 的参与,如此广泛地出现,那就很有必要进行下深入地学习和理解,避免错误用法导致的内存泄露等等问题。
0X00 Context 是什么
在了解 Context 之前,看看为啥要有它。Context 的中文意思是上下文,提供了获取上下文相关信息的接口。通过 Context 能够获得应用级别的信息,这些信息包括 PackageManager、 Resource、 uid、System Service 等等。而这些信息,对于各种操作都是非常有必要的,我们看看 Toast 的 makeText 方法。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 |
|
在 makeText 方法里面,通过 context 得到 LAYOUT_INFLATER_SERVICE 的系统服务。在其他需要 Context 的地方,也用着 Context 提供的各种信息。总结起来就是, Context 作为上下文环境信息的提供者,类似于一个工具集。
0X01 Context 架构
作为一个上下文环境,该如何实现呢?接下来直接明了地,看看 Context 具体的设计图。
Context 本身是一个抽象类,声明了作为一个 Context 对象需要实现的方法,也就是需要提供的上下文信息,例如getResources
,getPackageManager
等等。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 |
|
ContextWrapper 是其中的一个子类,这个是代理的实现,这种代理模式在 Binder 机制中也被使用,机制是相同的。通过构造函数,或者 attachBaseContext 函数传入 baseContext,而在实际的方法中,就通过这个 baseContext 来进行实际的操作。下面代码中的getResources
方法,演示了如何通过 baseContext 进行的调用。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
ContextImpl 是主要的实现类,实现了 Context 的大部分方法,针对 Application、Activity、Service 提供了对应的构造方法。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
|
ContextThemeWrapper 是在 ContextWrapper 的基础上,进行了主题相关的封装。因而 Activty 会继承这个,实现了主题相关的逻辑。而另一方面 Service 没有和主题相关的内容,这里继承自 ContextWrapper。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 |
|
0X02 Context 生命周期
根据前面的架构图,可以看到分别有 Application Context、Activity Context 和 Service Context 三种,接下来分析下他们的构建和销毁时间,这样可以帮助我们判断什么时候该用什么 Context。
Application Context
想看 Application Context 的创建时间,很自然地就会想到先看看 Application 的构建时候,也就是 ActivityThread 中的 handleBindApplication 方法。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
|
在 LoadedApk 中的 makeApplication 方法中,调用了 Instrumentation 的 newApplication 方法。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 |
|
Instrumentation 中的 newApplication 方法,调用了 Application 中的 attachBaseContext 方法,从这一步开始,Application Context 就暴露出去,并可以在应用中使用了。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 |
|
这个 Context 的生命周期和 Application 一致,一般情况下使用这个 Context 不会引发内存泄露等问题。
Activity Context
Activity 在启动的时候会进行 context 的创建,相关的代码在 ActivityThread 中的 perfromLaunchActivity 方法。
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
在 callActivityOnCreate 方法里,会执行 Activity 的 onCreate 方法,从这开始 Activity 这个 Context 就已经可用了。这里可以看到 Activity 与 新建的 context 紧紧地绑定在一起。如果我们在一些耗时操作中,引用了 Activity 这种 Context 就可能会导致内存泄露。
Service Context
[代码]java代码:
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
Service 与 Activity 类似,也是与 Service 同样生命周期。
0X04 各种 Context 的使用场景
共同学习,写下你的评论
评论加载中...
作者其他优质文章