Android开发中经常需要使用Context作为上下文,之前喜欢在Application中onCreate()定义,使用Kotlin后,还有跟好的方式,因此,这里做一下记录。
Kotlin 全局 Context 获取by lazy
正文
延迟获取
通过by lazy 获取 Context
延迟执行:变量在声明时不会立即执行初始化,而是等到代码中第一次真正访问该变量时,才执行大括号内的逻辑。
结果缓存:初始化代码只会执行一次,获取到的
Context会被缓存,后续访问直接返回缓存值。默认线程安全:
by lazy默认采用LazyThreadSafetyMode.SYNCHRONIZED模式,确保多线程环境下首次访问时只安全地初始化一次。
单例管理
object AppContextManager {
val globalContext: Context by lazy(LazyThreadSafetyMode.PUBLICATION) {
requireNotNull(AppGlobals.getInitialApplication()?.applicationContext) {
"Application Context is not initialized yet!"
}
}
}
// 使用:AppContextManager.globalContext顶层属性
// 文件: AppExtensions.kt
val globalContext: Context by lazy(LazyThreadSafetyMode.PUBLICATION) {
requireNotNull(AppGlobals.getInitialApplication()?.applicationContext) {
"Application Context is not initialized yet!"
}
}
// 使用:直接 import 后调用 globalContext之前都是通过Application.onCreate()获取context,这种比较老的,下面对比一下前后的区别
| 对比维度 | Application中获取 | 使用 by lazy |
|---|---|---|
| 执行时机 | App 启动,Application.onCreate() 被调用时立即执行。 | App 启动时不执行,直到业务代码首次访问时才初始化。 |
| 冷启动性能 | 在关键启动路径塞入初始化逻辑,可能拖慢启动速度。 | 实现延迟加载,将非核心初始化延后,优化冷启动性能。 |
| 线程安全 | 赋值给普通 var 全局变量时,需手动处理多线程可见性。 | 内部已处理并发访问,保证只安全地初始化一次。 |
| 架构设计 | 容易导致 Application 变成臃肿的“上帝类”。 | 可放在独立工具类或顶层文件中,做到职责单一。 |
注意事项
绝对禁止缓存Activity Context:
ApplicationContext生命周期与 App 一致,全局持有是安全的。但如果误将Activity Context缓存为全局变量,会导致 Activity 无法被回收,引发严重的内存泄漏。异常缓存机制:如果
AppGlobals.getInitialApplication()在首次访问时抛出异常,该异常会被lazy缓存,后续每次访问都会重复抛出同一个异常。必须确保AppGlobals在首次访问前已正确初始化。避免在 UI 场景滥用:凡是跟 UI 相关的操作(如启动 Activity、弹出 Dialog、Layout Inflate),都应该使用 Activity 作为 Context,不能使用全局的 ApplicationContext。

