在 Android 中,Handler 机制是一套用于线程间通信的核心机制,主要解决 "子线程无法直接更新 UI" 的问题(Android 规定 UI 操作必须在主线程执行,否则会抛出异常),同时也用于实现延迟任务、定时任务等场景。
1. Message(消息)
- 是线程间传递的数据载体,可携带简单数据(如
what
、arg1
、arg2
)或复杂对象(obj
)。 - 为了避免频繁创建对象,可通过
Message.obtain()
从消息池获取(复用机制),比new Message()
更高效。
2. MessageQueue(消息队列)
- 是一个单链表结构 的队列,用于存储
Handler
发送的Message
,按消息的触发时间(when
)排序(早触发的在前)。 - 每个线程最多只有一个
MessageQueue
,由Looper
创建并管理。
3. Looper(消息循环器)
- 是 "消息循环" 的核心,负责不断从 MessageQueue 中取出消息 ,并分发到对应的
Handler
处理。 - 每个线程最多只有一个
Looper
(通过ThreadLocal
实现线程隔离,确保线程私有)。 - 主线程(UI 线程)在启动时会自动初始化
Looper
(通过ActivityThread.main()
方法),因此主线程可直接使用Handler
;子线程若要使用Handler
,需手动调用Looper.prepare()
初始化Looper
,再调用Looper.loop()
启动循环。
4. Handler(处理器)
- 负责发送消息到 MessageQueue (如
sendMessage()
、post()
等方法),并处理 Looper 分发的消息 (重写handleMessage()
方法)。 - 一个
Handler
关联一个Looper
(创建时默认绑定当前线程的Looper
),因此可通过Handler
将消息从一个线程发送到另一个线程的MessageQueue
。
工作流程
- 初始化 Looper :线程启动时,若需使用 Handler 机制,需通过
Looper.prepare()
创建Looper
和对应的MessageQueue
(主线程默认初始化)。 - 创建 Handler :在目标线程(如主线程)创建
Handler
,它会自动绑定当前线程的Looper
和MessageQueue
。 - 发送消息 :其他线程(如子线程)通过
Handler
的sendMessage()
(发送Message
)或post()
(发送Runnable
,内部会包装为Message
)将消息加入MessageQueue
。 - 消息循环 :
Looper.loop()
启动死循环,不断从MessageQueue
中取出消息(若队列空则阻塞,释放 CPU),并通过Message
中关联的Handler
分发消息。 - 处理消息 :
Handler
收到消息后,通过dispatchMessage()
方法处理(优先执行Message
的Runnable
,其次是Handler
的handleMessage()
)。
关键细节
- 线程与 Looper 的关系:1 个线程 → 1 个 Looper → 1 个 MessageQueue → N 个 Handler(多个 Handler 可绑定同一 Looper)。
- Looper 的死循环为何不 ANR :当
MessageQueue
为空时,Looper
会阻塞在next()
方法(通过 Linux 的epoll
机制休眠),不占用 CPU;有新消息时会被唤醒,因此不会导致 ANR。 - 内存泄漏风险 :若
Handler
是 Activity 的非静态内部类,会持有 Activity 的强引用;若消息在队列中延迟未处理,会导致 Activity 无法被回收(内存泄漏)。解决:将Handler
定义为静态内部类 ,并通过弱引用(WeakReference) 持有 Activity;在 Activity 销毁时(onDestroy()
)调用handler.removeCallbacksAndMessages(null)
移除所有消息。
典型场景
- 子线程执行耗时操作(如下载、数据库查询)后,通过
Handler
通知主线程更新 UI。 - 实现延迟任务(如
handler.postDelayed(runnable, 1000)
)。 - 主线程向子线程发送指令(如停止子线程的任务)。
1.子线程→主线程通信
kotlin
class MainActivity : AppCompatActivity() {
companion object {
private const val TAG = "HandlerDemo"
private const val WHAT_UPDATE = 2
}
// 后台线程与其 Handler(示例使用 HandlerThread)
private lateinit var workerThread: HandlerThread
private lateinit var workerHandler: Handler
// 界面元素:用于展示处理结果
private lateinit var statusText: TextView
private lateinit var actionButton: Button
// Message 处理示例:在主线程中统一处理结构化消息
private val messageHandler = object : Handler(Looper.getMainLooper()) {
override fun handleMessage(msg: Message) {
when (msg.what) {
WHAT_UPDATE -> {
val text = "Updated: ${msg.obj}"
Log.d(TAG, "handleMessage WHAT_UPDATE: ${msg.obj}")
// 更新到界面
if (::statusText.isInitialized) {
statusText.text = text
}
}
else -> {
Log.d(TAG, "handleMessage what=${msg.what}")
}
}
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
// 绑定 TextView,用于展示主线程/后台线程的处理结果
statusText = findViewById(R.id.statusText)
actionButton = findViewById(R.id.actionButton)
// 2) HandlerThread:创建后台线程并投递任务
workerThread = HandlerThread("DemoWorker")
workerThread.start()
workerHandler = Handler(workerThread.looper)
// 点击按钮后触发:仅演示子线程 -> 主线程通信
actionButton.setOnClickListener {
statusText.text = "Starting..."
// 后台线程:执行任务并通过 Message 回到主线程
workerHandler.post {
Log.d(TAG, "workerHandler.post on ${Thread.currentThread().name}")
Thread.sleep(300)
val msg = messageHandler.obtainMessage(WHAT_UPDATE, "Result from worker")
messageHandler.sendMessage(msg)
}
}
}
override fun onDestroy() {
super.onDestroy()
// 清理消息与回调,避免泄漏;安全退出后台线程
messageHandler.removeCallbacksAndMessages(null)
if (::workerThread.isInitialized) {
workerThread.quitSafely()
}
}
}
2.实现延迟任务
kotlin
// 后台线程:延迟启动任务,然后立即把结果发回主线程
Log.d(TAG, "schedule workerHandler.postDelayed(+5s)")
workerHandler.postDelayed({
Log.d(TAG, "workerHandler.postDelayed on ${Thread.currentThread().name}")
Thread.sleep(300)
val msg = messageHandler.obtainMessage(WHAT_UPDATE, "Result from worker (delayed start)")
messageHandler.sendMessage(msg)
}, 5000L)