深入理解 Android 的 Context:你用对了吗?

Context 是什么?

Context 是 Android 中最核心的抽象之一,它代表了一个应用环境的全局信息。几乎所有 Android 组件都需要 Context——启动 Activity、创建 View、访问资源、打开数据库,都离不开它。

Context 的类型

整个应用进程中存在两种 Context:

  • Application Context:与应用生命周期绑定。getApplicationContext() 返回。全局唯一。
  • Activity Context:与 Activity 生命周期绑定。this 或 getContext()(在 Activity 中)。
// Application Context
val appCtx = context.applicationContext
// Activity Context
val activityCtx = this  // 在 Activity 内部

什么时候用哪个?

场景 推荐 Context
启动 Activity Activity Context(需要任务栈信息)
显示 Dialog Activity Context
Layout Inflation Activity Context(会使用正确主题)
Toast Application Context
初始化单例 Application Context(避免内存泄漏!)
启动 Service Activity Context(Android 8.0+ 有限制)
获取资源(string/color/drawable) 两者均可
注册 BroadcastReceiver 两者均可,取决于生命周期需求

常见错误

1. 单例持有 Activity Context

// ❌ 危险!Activity 无法被 GC
object UserManager {
    lateinit var context: Context
}

// ✅ 正确做法
object UserManager {
    lateinit var context: Application
    fun init(app: Application) {
        context = app
    }
}

2. 使用 Application Context 显示 Dialog

// ❌ 会崩溃:Unable to add window — token null
AlertDialog.Builder(applicationContext).show()

// ✅ 使用 Activity Context
AlertDialog.Builder(this).show()  // this 是 Activity

3. 静态变量持有 View 引用

// ❌ View 隐式持有 Activity Context
companion object {
    var staticView: View? = null
}

Context 的继承关系

Context 是一个抽象类,有两个直接子类:ContextWrapper 和 ContextImpl。Activity、Application、Service 都继承自 ContextWrapper,内部持有一个 ContextImpl 实例作为真正的实现。

总结

记住一条黄金法则:如果引用的生命周期比 Activity 长,就用 ApplicationContext,否则用 Activity Context。这样你就能避免大部分 Context 相关的内存泄漏问题。

沪ICP备2026038898号-1