Android Handler 机制深度解析
1. Handler 机制的核心组件
1.1 Handler
-
作用:
- 发送消息到
MessageQueue。 - 处理
Looper分发的消息。
- 发送消息到
-
关键方法:
public void handleMessage(@NonNull Message msg) {} // 需子类重写 public final boolean sendMessage(@NonNull Message msg) {} public final boolean post(@NonNull Runnable r) {}
1.2 Looper
-
作用:
- 通过死循环 (
loop()) 从MessageQueue中取出消息。 - 将消息分发给对应的
Handler。
- 通过死循环 (
-
核心代码:
public static void loop() { while (true) { Message msg = queue.next(); // 从 MessageQueue 取消息 msg.target.dispatchMessage(msg); // 分发消息 } }
1.3 MessageQueue
-
作用:
- 存储消息的队列(链表结构)。
- 管理线程休眠与唤醒(通过
nativePollOnce和nativeWake)。
-
消息插入与取出:
enqueueMessage():插入消息并按时间排序。next():取出消息(无消息时线程休眠)。
1.4 Message
-
结构:
public final class Message { Handler target; // 目标 Handler Runnable callback; // Runnable 任务 Object obj; // 携带的数据 int what; // 消息标识 Message next; // 链表结构的下一个消息 }
2. 消息处理流程
2.1 发送消息
-
通过
sendMessage:Handler handler = new Handler(); Message msg = handler.obtainMessage(1); // what = 1 handler.sendMessage(msg); -
通过
post:handler.post(() -> { // 执行任务 });
2.2 消息分发
-
dispatchMessage()的逻辑:public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); // 执行 Runnable } else if (mCallback != null) { mCallback.handleMessage(msg); // 全局 Callback 处理 } else { handleMessage(msg); // 子类处理 } }
3. Thread.sleep() 与 interrupt() 的区别
| 特性 | Thread.sleep() | Thread.interrupt() |
|---|---|---|
| 作用 | 让线程休眠指定时间 | 设置线程中断状态 |
| 是否释放锁 | 不释放锁 | 不涉及锁 |
| 异常 | 休眠时被中断会抛 InterruptedException | 中断阻塞操作会抛 InterruptedException |
| 中断状态 | 抛异常后清除中断状态 | 直接设置中断状态 |
4. nativePollOnce 与 nativeWake 的作用
4.1 nativePollOnce
- 功能:让线程进入低功耗休眠状态。
- 实现:基于
epoll监听文件描述符事件。 - 场景:当
MessageQueue为空时调用。
4.2 nativeWake
- 功能:唤醒休眠的线程。
- 场景:当新消息插入
MessageQueue时调用。
4.3 对比 Thread.sleep()
| 特性 | nativePollOnce | Thread.sleep() |
|---|---|---|
| 功耗 | 低功耗(完全休眠) | 较高(定期唤醒) |
| 响应速度 | 事件驱动(快速响应) | 依赖定时器(较慢) |
| 系统集成 | 支持监听文件描述符事件 | 仅支持定时休眠 |
5. 同步消息与异步消息
5.1 同步消息
-
默认行为:按插入顺序处理。
-
发送方式:
handler.sendMessage(msg);
5.2 异步消息
-
标记方法:
msg.setAsynchronous(true); -
使用场景:需要优先处理的任务(如 UI 更新)。
6. post() 与 sendMessage() 的区别
| 特性 | post() | sendMessage() |
|---|---|---|
| 参数类型 | Runnable | Message |
| 处理方式 | 直接执行 Runnable.run() | 调用 handleMessage() |
| 是否需要继承 | 否 | 是(需重写 handleMessage()) |
7. 常见问题解答
7.1 为什么 post() 无法触发 handleMessage()?
- 原因:
post()会将Runnable赋值给Message.callback,而dispatchMessage()优先执行callback。 - 解决方案:改用
sendMessage()或结合两者使用。
7.2 runOnUiThread() 的原理是什么?
-
源码:
public final void runOnUiThread(Runnable action) { if (isMainThread()) action.run(); else mHandler.post(action); } -
本质:通过
Handler.post()在主线程执行任务。
7.3 如何监听 post() 的消息?
- 直接处理:在
Runnable中实现逻辑。 - 间接通知:在
Runnable中发送Message。
总结
- Handler 机制:基于生产者-消费者模型,实现线程间通信。
- 核心设计:通过
nativePollOnce和nativeWake优化性能与功耗。 - 灵活使用:根据需求选择
post()(执行任务)或sendMessage()(处理消息)。