Context 在 Android 中被描述为 “关于应用环境的全局信息接口”。它贯穿整个 Android 框架,是访问系统资源、启动组件、获取系统服务的入口。然而,Context 的继承层级、不同类型的 Context 之间的差异、以及使用不当可能导致的内存泄漏,是深入理解 Android 框架不可或缺的知识。本文深入分析 Context 的继承体系、ContextImpl 的创建过程以及各类型 Context 的差异。
一、Context 的继承体系
1.1 类图
abstract Context |
或从 ContextImpl 角度:
Context (abstract) |
AOSP 路径:
frameworks/base/core/java/android/content/Context.javaframeworks/base/core/java/android/content/ContextWrapper.javaframeworks/base/core/java/android/app/ContextImpl.javaframeworks/base/core/java/android/view/ContextThemeWrapper.java
1.2 ContextWrapper——装饰器模式的经典应用
ContextWrapper 是装饰器模式的典型实现,它持有一个 Context 引用(mBase),所有方法默认委托给 mBase:
// frameworks/base/core/java/android/content/ContextWrapper.java |
这一设计的精妙之处在于:Activity、Service、Application 这些类都是 ContextWrapper 的子类,但它们内部的 mBase 指向的是同一个 ContextImpl 类型。也就是说,真正干活的是 ContextImpl,而 ContextWrapper 及其子类只是提供了不同的”视角”(比如 Activity 多了主题支持)。
二、ContextImpl——Context 的真正实现
2.1 ContextImpl 的核心字段
// frameworks/base/core/java/android/app/ContextImpl.java |
2.2 ContextImpl 的创建
不同类型的 Context 有不同的创建方式,但都通过 ContextImpl 的静态工厂方法创建:
// frameworks/base/core/java/android/app/ContextImpl.java |
2.3 ActivityThread 中创建 Context
// frameworks/base/core/java/android/app/ActivityThread.java |
三、不同类型 Context 的差异
3.1 Application Context vs Activity Context
这是最容易混淆的一组概念:
| 特性 | Application Context | Activity Context |
|---|---|---|
| 生命周期 | 伴随整个应用进程 | 伴随 Activity 生命周期 |
| 主题支持 | 无(不是 ContextThemeWrapper) | 有(继承 ContextThemeWrapper) |
| startActivity | 需要 NEW_TASK flag | 不需要(默认放入当前 Task) |
| inflate layout | 使用默认主题 | 使用 Activity 主题 |
| 显示 Dialog | 不允许(需要 Window token) | 允许 |
3.2 getSystemService 的实现
Context 的 getSystemService 是获取系统服务的统一入口:
// frameworks/base/core/java/android/app/ContextImpl.java |
每个系统服务在静态代码块中注册工厂,首次调用时创建,之后通过缓存返回。
3.3 Service 的 Context
// frameworks/base/core/java/android/app/Service.java |
Service 直接继承 ContextWrapper(不是 ContextThemeWrapper),因此它没有主题支持,这也就是为什么你不能在 Service 中 inflate layout 并使用 Activity 主题。
3.4 ContentProvider 的 Context
ContentProvider 在 onCreate() 被调用前通过 attachInfo() 方法绑定 Context。它同样继承 ContextWrapper,生命周期与 Application 相同:
// frameworks/base/core/java/android/content/ContentProvider.java |
四、Context 的内存泄漏分析
4.1 常见泄漏场景
场景1:静态变量持有 Activity Context
public class MyManager { |
解法:使用 context.getApplicationContext() 或让静态变量持有 Application Context。
场景2:单例持有 Activity 引用:如 EventBus 注册了 Activity 但未解注册。
场景3:内部类/匿名类隐式持有外部类引用:如 Handler、AsyncTask 作为 Activity 的非静态内部类,它们持有对外部 Activity 的隐式引用。如果 Handler 消息延迟较长,Activity 在消息执行前被销毁,就会泄漏。
五、Context 在资源加载中的角色
ContextImpl 持有 Resources 对象,负责:
- 资源加载:
getResources().getString(R.string.xxx)、getResources().getDrawable(R.drawable.xxx) - AssetManager:管理 APK 内的 assets 目录文件
- 数据库:
openOrCreateDatabase()创建 SQLiteDatabase - 文件操作:
openFileInput()、openFileOutput()等 - SharedPreferences:
getSharedPreferences()持久化键值对
这些操作的底层都依赖于 ContextImpl 中持有的 LoadedApk mPackageInfo 对象:
// frameworks/base/core/java/android/app/ContextImpl.java |
六、核心面试题
Q1:Application Context 和 Activity Context 有什么区别?什么时候用哪个?
核心区别在于生命周期和窗口关联能力。Application Context 生命周期等于进程生命周期,适合用于单例、数据库、网络库初始化等需要全局 Context 的场景。Activity Context 带有主题和窗口令牌,适合用于 UI 相关操作(显示 Dialog、inflate layout 需要 Activity 主题、startActivity 不带 NEW_TASK 等)。一个关键原则:只要生命周期需要跟随 Activity 的资源(如 Dialog、Toast 的某些场景),就用 Activity Context;否则优先使用 Application Context 避免内存泄漏。
Q2:getApplication() 和 getApplicationContext() 返回的是同一个对象吗?
是同一个对象。getApplication() 返回的是当前进程的 Application 实例(继承自 ContextWrapper),getApplicationContext() 返回的是 Context 实例。在 Activity 或 Service 中,getApplicationContext() 返回的就是 Application 对象本身(因为 Application 实现了 Context 接口链)。从语义上说,getApplicationContext() 强调的是 “这是一个适合长时间持有的 Context”,而 getApplication() 返回的是其 Application 类型。
Q3:为什么 Activity 可以直接调用 startActivity 而不需要 FLAG_ACTIVITY_NEW_TASK?
因为 Activity 继承了 ContextThemeWrapper→ContextWrapper→Context,其内部的 ContextImpl 持有 Activity 的 token(与 WMS 的 IApplicationToken 关联),在调用 startActivity 时,系统会根据调用者的 token 自动确定目标 Activity 放入哪个 Task。而 Application Context 不持有任何 Activity 的 token,因此必须在 Intent 中显式设置 FLAG_ACTIVITY_NEW_TASK。
AOSP 核心路径参考:
frameworks/base/core/java/android/content/Context.javaframeworks/base/core/java/android/content/ContextWrapper.javaframeworks/base/core/java/android/app/ContextImpl.javaframeworks/base/core/java/android/app/SystemServiceRegistry.javaframeworks/base/core/java/android/view/ContextThemeWrapper.javaframeworks/base/core/java/android/app/ActivityThread.java





