Handler() 已弃用:现在怎么办?展望 2025 年
\n\n如果你曾经编写过 Android 代码,那么你肯定使用过 Handler() 来在线程之间切换、执行延迟任务或更新 UI。这个久经考验的类从 Android 最初的版本就一直伴随着我们。但在 2024-2025 年,Google 正式宣布 Handler() 构造函数 deprecated(已弃用)。成千上万的开发者在 Stack Overflow 上提问:“Handler() 已弃用,我现在该用什么?”
在本文中,我们将探讨为什么 Handler() 会被弃用,Android 在 2025 年提供了哪些替代方案,最重要的是——如何用 Kotlin 编写不会让你的技术主管头疼的现代、干净的代码。开始吧!
为什么 Handler() 被弃用了?
\n\nHandler 类本身并没有消失。被弃用的实际上是 无参构造函数(Handler())及其重载,它们会隐式地从当前线程创建 Looper。问题在于这种行为:
- \n
- 隐式且不安全——如果在没有
Looper的后台线程中调用Handler(),你会得到一个RuntimeException。 \n - 使测试复杂化——
Handler与线程生命周期紧密耦合,使得单元测试变得令人头疼。 \n - 在理念上过时——出现了更现代、更声明式的工具:协程、显式
HandlerThread和LiveData。 \n
Google 建议显式地将 Looper 传递给构造函数,或者使用替代方案。让我们看看具体有哪些替代方案。
替代方案 #1:显式 Looper(最简单的修复)
\n\n如果你不想重写所有代码,消除弃用警告的最快方法是显式传递 Looper。对于主线程(UI 线程),使用 Looper.getMainLooper()。
// 旧代码(已弃用)\nval handler = Handler()\n\n// 新代码(2025)\nval handler = Handler(Looper.getMainLooper())\n\n// 或者用于后台线程:\nval handler = Handler(Looper.myLooper()) // 注意:可能为 null!\n\n\n这并不能解决所有问题,但会消除编译器的警告。不过,对于严肃的项目,最好迁移到协程。
\n\n替代方案 #2:Kotlin Coroutines(Google 推荐)
\n\n自 2021 年起,Google 正式推荐使用 Kotlin Coroutines 进行异步操作。到 2025 年,这已成为行业标准。为什么协程比 Handler 更好?
- \n
- 轻量级——数千个协程不会阻塞线程。 \n
- 结构化并发——在生命周期结束时自动取消。 \n
- 可读性——代码看起来像同步代码,没有回调。 \n
- 可测试性——
runBlocking和TestCoroutineDispatcher用于单元测试。 \n
以下是如何用协程替换典型的 Handler 任务:
替换 postDelayed(延迟任务)
\n\n// 使用 Handler 的旧方法\nval handler = Handler(Looper.getMainLooper())\nhandler.postDelayed({\n // 2 秒后执行\n}, 2000)\n\n// 使用 Coroutines 的新方法\nlifecycleScope.launch {\n delay(2000) // 不阻塞线程!\n // 2 秒后执行\n}\n\n\n替换 post(切换到 UI 线程)
\n\n// 旧方法\nhandler.post {\n textView.text = "来自后台线程的问候"\n}\n\n// 新方法\nlifecycleScope.launch(Dispatchers.Main) {\n textView.text = "来自协程的问候"\n}\n\n\n替换 removeCallbacks(取消任务)
\n\n// 旧方法\nval runnable = Runnable { /*...*/ }\nhandler.postD