全局获取 Context 的技巧(Android)

在 Android 开发中,我们经常需要获取 Context,例如启动 Activity、创建 View、访问资源、使用系统服务等。但不恰当地获取或保留 Context 会导致内存泄漏等问题。

本篇文章介绍几种安全、规范地全局获取 Context 的技巧,并说明哪些方式应当避免。


为什么需要全局 Context?

一些典型的使用场景:

  • 初始化第三方 SDK
  • 弹 Toast 消息
  • 获取系统服务(如 ClipboardManager
  • 访问资源文件(getString()getDrawable() 等)

正确方式:使用 Application Context

方法 1:自定义 Application 类

1
2
3
4
5
6
7
8
9
10
11
12
class MyApp : Application() {

override fun onCreate() {
super.onCreate()
appContext = applicationContext
}

companion object {
lateinit var appContext: Context
private set
}
}

AndroidManifest.xml 中注册:

1
2
3
4
<application
android:name=".MyApp"
...>
</application>

使用方式:

1
val ctx = MyApp.appContext

优点:

  • 生命周期和 App 一致,不会泄漏
  • 适用于 Toast、资源访问、初始化等场景

注意:

  • 不可用于 UI 创建(如 Dialog(this)),需要传入 Activity Context

方法 2:使用 Singleton + Application Context

适用于工具类或管理类中:

1
2
3
4
5
6
object ToastUtil {

fun show(msg: String) {
Toast.makeText(MyApp.appContext, msg, Toast.LENGTH_SHORT).show()
}
}

错误示范(⚠️避免):

❌ 静态保存 Activity Context

1
2
3
object MyManager {
var context: Context? = null
}

这会导致 Activity 无法被回收,严重时引发内存泄漏。

❌ 使用 View.getContext() 做非 UI 操作

View 的 Context 实际上是 Activity,一旦页面销毁仍保留引用,也可能泄漏。


Jetpack 推荐方式(进阶)

在使用 ViewModel、Hilt、Jetpack Compose 时,建议使用依赖注入(DI)或 SavedStateHandle 等方式获取 Context,更加灵活和可测试。

例如使用 Hilt:

1
2
3
4
@HiltViewModel
class MyViewModel @Inject constructor(
@ApplicationContext val context: Context
) : ViewModel()

总结

获取方式 是否推荐 说明
applicationContext ✅ 推荐 生命周期长,不易泄漏
自定义 Application 保存 context ✅ 推荐 全局工具类中使用
Activity / View context 静态持有 ❌ 避免 易泄漏内存
依赖注入框架注入 context ✅ 推荐 可测试性好,架构现代

最佳实践

  • 避免传递 Context 给单例或静态类
  • 只在需要 UI 的地方使用 Activity Context
  • 工具类中尽可能使用 Application Context
  • 引入 Hilt / Koin 等依赖注入框架管理依赖

希望这篇文章能帮助你在项目中更好地管理 Context,避免常见陷阱。如果你有其他技巧或问题,欢迎留言交流!