深度解析 Handler 机制:从基础用法到内存泄漏规避

张开发
2026/4/18 18:56:42 15 分钟阅读

分享文章

深度解析 Handler 机制:从基础用法到内存泄漏规避
1. 前言为什么 Android 离不开 Handler在 Android 开发中为了保证 UI 交互的流畅性系统规定只有主线程UI 线程才能更新 UI。但在实际开发中我们经常需要处理耗时任务如请求网络、读取数据库。如果这些任务放在主线程会造成页面卡顿甚至 ANR应用无响应。这就诞生了Handler它是子线程与主线程之间通信的桥梁。2. Handler 的基础用法子线程更新 UI我们来看一个最经典的场景在子线程模拟网络请求获取数据后更新界面。class MainActivity : AppCompatActivity() { private lateinit var tvResult: TextView // 1. 在主线程创建 Handler // 注意Handler() 无参构造函数已过时必须显式指定 Looper private val mHandler object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { super.handleMessage(msg) if (msg.what 1) { // 3. 接收消息并更新 UI val result msg.obj as String tvResult.text result } } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) tvResult findViewById(R.id.tv_result) // 2. 开启子线程模拟耗时操作 thread { Thread.sleep(2000) // 模拟耗时 val message Message.obtain().apply { what 1 obj 来自 Kotlin 子线程的消息 } mHandler.sendMessage(message) } } }3. 避坑指南Kotlin 中 Handler 的内存泄漏在 Kotlin 中直接使用 object : Handler()... 同样会持有 Activity 的隐式引用导致内存泄漏。【黄金标准】静态内部类 弱引用的 Kotlin 实现class BetterActivity : AppCompatActivity() { private lateinit var mHandler: MyHandler override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) mHandler MyHandler(this) } // 在 Kotlin 中直接定义的内部类默认就是静态内部类不持有外部引用 // 如果需要持有外部引用需要加 inner 关键字 private class MyHandler(activity: BetterActivity) : Handler(Looper.getMainLooper()) { // 使用弱引用防止内存泄漏 private val weakActivity WeakReference(activity) override fun handleMessage(msg: Message) { val activity weakActivity.get() activity?.let { // 在这里安全地处理 UI 更新 if (msg.what 1) { it.tvResult.text 安全地接收到消息 } } } } override fun onDestroy() { // 记得在 Activity 销毁时清理消息队列 mHandler.removeCallbacksAndMessages(null) super.onDestroy() } }4. 深度原理Handler 的“四剑客”在面试中理解这四个组件的配合至关重要Message (消息)包含数据的“包裹”。MessageQueue (消息队列)存放消息的堆栈由 Looper 管理。Looper (轮询器)核心发动机。Looper.prepare() 初始化Looper.loop() 开启死循环。Handler (处理器)负责发送sendMessage和处理handleMessage消息。Kotlin 小知识在 Kotlin 中我们可以利用 runBlocking 或 launch 协程来处理大部分 Handler 的场景但在处理系统级回调时Handler 依然是唯一的选择。欢迎点赞关注我们共同进步

更多文章