Context 基本概念
Context 是一个抽象类,它代表了应用程序的环境信息。主要用途包括:
- 访问应用程序资源
- 启动 Activity、Service
- 获取系统服务
- 获取应用程序目录
- 创建 UI 组件
Context 的类型
-
Application Context
- 生命周期最长,与应用程序生命周期一致
- 通过
getApplicationContext()获取 - 适用于单例模式
-
Activity Context
- 生命周期与 Activity 一致
- Activity 本身就是 Context
- 用于 UI 相关操作
-
Service Context
- 生命周期与 Service 一致
- Service 本身也是 Context
使用示例
class ExampleActivity : AppCompatActivity() {
fun contextExample() {
// 1. 获取资源
val drawable = context.getDrawable(R.drawable.icon)
// 2. 启动 Activity
val intent = Intent(context, SecondActivity::class.java)
startActivity(intent)
// 3. 获取系统服务
val layoutInflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
// 4. 获取应用目录
val filesDir = context.filesDir
}
}
注意事项
- 内存泄漏风险
- 避免在单例中持有 Activity Context
- 使用 Application Context 代替 Activity Context(适用场景下)
// 错误示例
class MySingleton private constructor(private val context: Context) {
companion object {
@Volatile private var instance: MySingleton? = null
fun getInstance(context: Context): MySingleton {
return instance ?: synchronized(this) {
instance ?: MySingleton(context).also { instance = it }
}
}
}
}
// 正确示例
class MySingleton private constructor(private val context: Context) {
companion object {
@Volatile private var instance: MySingleton? = null
fun getInstance(context: Context): MySingleton {
return instance ?: synchronized(this) {
instance ?: MySingleton(context.applicationContext).also { instance = it }
}
}
}
}
-
选择合适的 Context
- UI 相关操作使用 Activity Context
- 应用级别操作使用 Application Context
- 注意生命周期影响
-
避免 Context 泄露
- 在异步操作中使用 WeakReference
- 及时释放不需要的 Context 引用
class MyAsyncTask(activity: Activity) {
private val activityReference: WeakReference<Activity> = WeakReference(activity)
fun doInBackground() {
val activity = activityReference.get() ?: return
// 使用 activity
}
}
- 不要传递错误的 Context
- Dialog 要使用 Activity Context,不能使用 Application Context
- Toast 可以使用 Application Context
最佳实践
- 需要在应用程序整个生命周期中使用的场景,使用 Application Context
- 涉及到 UI 操作的场景,使用 Activity Context
- 在单例模式中,优先使用 Application Context
- 注意处理异步操作中的 Context 引用
- 根据实际场景选择合适的 Context 类型
记住这些原则可以帮助你避免很多常见的 Context 相关问题,写出更稳定的应用程序。