共计 2161 个字符,预计需要花费 6 分钟才能阅读完成。
背景与痛点
在 Android 开发中,Activity 是最常用的组件之一。Activity 的创建、销毁和切换过程中,系统会为其分配一个唯一的 Token 标识。这个 Token 对 Activity 的生命周期管理至关重要,但很多新手开发者往往忽视了它的存在,导致各种问题。

- Token 的作用:Token 是系统识别和管理 Activity 的关键标识,确保 Activity 能够正确响应系统事件(如配置变更、内存回收等)。
- 常见误区:开发者常因不了解 Token 机制而引发以下问题:
- 内存泄漏:Activity 被销毁后,Token 未被正确释放,导致 Activity 实例无法被回收。
- 崩溃:跨进程传递 Token 时处理不当,可能引发
BadTokenException等异常。 - 生命周期混乱:Token 与 Activity 绑定不匹配时,可能导致生命周期回调错乱。
核心概念
Token 的本质是一个 Binder 对象,由 ActivityRecord 在系统服务端生成,并通过 ActivityThread 传递给客户端(即应用进程)。以下是其工作原理的关键点:
- Token 的生成与传递:
- 系统启动 Activity 时,
ActivityManagerService会为其创建唯一的 Token。 -
Token 通过 Binder 跨进程传递给应用进程,绑定到
Activity实例上。 -
Token 与 Window 的关系:
- Token 是
Window与Activity关联的桥梁。WindowManager通过 Token 验证View的归属。 -
如果 Token 无效(如 Activity 已销毁),
WindowManager会拒绝视图的添加或更新。 -
Token 的生命周期:
- Token 的生命周期与 Activity 严格绑定,Activity 销毁时 Token 会被系统回收。
- 开发者不应手动持有或缓存 Token,否则可能引发内存泄漏。
技术方案
正确使用 Token 的代码示例
以下是一个避免 Token 问题的典型场景:在异步任务中更新 UI 时检查 Activity 状态。
class MainActivity : AppCompatActivity() {private val handler = Handler(Looper.getMainLooper())
override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// 模拟异步任务
thread {
// 耗时操作
Thread.sleep(2000)
handler.post {
// 检查 Activity 是否有效
if (!isDestroyed) {findViewById<TextView>(R.id.text_view).text = "更新成功"
}
}
}
}
}
关键注释
isDestroyed检查:确保异步回调时 Activity 未被销毁,避免因无效 Token 导致BadTokenException。- Handler 的使用:通过主线程 Handler 更新 UI,防止非 UI 线程直接操作视图。
性能与安全
潜在问题
- 内存泄漏:
- 匿名内部类或长生命周期对象隐式持有 Activity 引用(如
Handler、Runnable),导致 Token 无法释放。 -
解决方案:使用静态内部类 + 弱引用,或依赖
Lifecycle组件(如ViewModel)。 -
安全风险:
- 跨进程传递 Token 时,恶意应用可能伪造 Token 劫持 Activity。
- 解决方案:避免通过
Intent传递 Token,依赖系统级绑定(如PendingIntent)。
优化建议
- 使用
ViewBinding或DataBinding: -
自动管理视图引用,减少手动处理 Token 的机会。
-
依赖
Lifecycle组件: -
LifecycleOwner提供更安全的生命周期感知能力。 -
避免全局缓存 Activity:
- 如必须缓存,使用
WeakReference并定期清理。
避坑指南
常见错误及解决方案
BadTokenException:- 场景 :在 Activity 销毁后尝试显示
Dialog或Toast。 -
解决 :检查
isFinishing或isDestroyed状态。 -
内存泄漏:
- 场景 :
Handler或匿名类持有 Activity 引用。 -
解决 :改用
WeakReference或Lifecycle-aware组件。 -
跨进程 Token 失效:
- 场景 :通过
AIDL传递 Activity 的 Token。 - 解决 :使用
RemoteCallback或ResultReceiver替代。
互动引导
建议读者尝试以下实践,观察 Token 的行为:
- 在异步任务中延迟更新 UI,手动旋转设备触发配置变更,观察未检查
isDestroyed时的崩溃日志。 - 使用
LeakCanary检测 Activity 泄漏,对比有无WeakReference时的内存差异。 - 通过
adb shell dumpsys activity命令查看系统层 Token 的分配情况。
通过这些小实验,可以更直观地理解 Token 的机制及其重要性。
结语
Token 是 Android 框架中一个看似透明但极其关键的机制。作为开发者,理解其原理不仅能避免常见的崩溃和泄漏问题,还能优化应用的整体稳定性。希望本文能帮助你从新手进阶为更严谨的 Android 开发者。
