温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

handler的执行顺序是怎么样的

发布时间:2021-12-16 16:43:54 来源:亿速云 阅读:402 作者:iii 栏目:云计算
# Handler的执行顺序是怎么样的 ## 引言 在Android开发中,`Handler`作为线程间通信的核心组件,其执行顺序直接影响着消息处理的正确性和性能表现。本文将深入剖析Handler的消息处理机制,从消息入队到最终执行的完整流程,帮助开发者掌握Handler的工作时序,避免常见的时序错误。 ## 一、Handler基础架构回顾 ### 1.1 核心组件关系 ```java // 典型Handler使用示例 Handler handler = new Handler(Looper.getMainLooper()) { @Override public void handleMessage(Message msg) { // 处理消息 } }; 

Android消息机制由三大核心组件构成: - MessageQueue:消息存储队列(单链表实现) - Looper:消息循环泵,负责从队列提取消息 - Handler:消息处理器,承担发送和处理双重角色

1.2 消息循环流程

发送端Handler -> MessageQueue.enqueueMessage() ↓ Looper.loop() -> MessageQueue.next() ↓ 目标Handler.dispatchMessage() 

二、消息入队顺序分析

2.1 同步发送时序

handler.sendMessage(msg1); handler.sendMessage(msg2); // 执行顺序:msg1 → msg2 

同步发送时,消息按调用顺序严格进入队列尾部,形成FIFO(先进先出)结构。这种顺序在单线程环境下绝对可靠。

2.2 异步消息的特殊性

Message msg = Message.obtain(); msg.setAsynchronous(true); // 标记为异步消息 handler.sendMessage(msg); 

异步消息(通过setAsynchronous(true)标记)在API 16+引入,主要用于系统级高优先级消息(如VSync事件),但在普通消息队列中仍按入队时间排序。

2.3 延迟消息的队列插入

handler.sendMessageDelayed(msg1, 1000); // 1秒延迟 handler.sendMessage(msg2); // 立即发送 

延迟消息通过when字段记录目标执行时间: 1. 消息入队时根据SystemClock.uptimeMillis() + delay计算when 2. MessageQueue按when值升序排列 3. 即使后发送的msg2也会因更小的when值排在msg1前

三、消息出队处理顺序

3.1 Looper的提取逻辑

// 伪代码展示Native层消息提取 Message next() { for (;;) { nativePollOnce(ptr, timeout); synchronized (this) { Message prev = null; Message msg = mMessages; // 寻找符合条件的消息 if (msg != null && msg.when <= now) { // 出队操作... return msg; } } } } 

关键处理规则: 1. 总是取队列头部满足when <= currentTime的消息 2. 遇到未到时的消息会进入native休眠 3. 新消息插入头部时会触发native唤醒

3.2 屏障消息(Barrier)机制

// 系统内部使用代码 mQueue.postSyncBarrier(); 

特殊场景下的顺序调整: 1. 同步屏障(token != 0的消息)会阻塞后续同步消息 2. 只有异步消息能越过屏障处理 3. 屏障移除后恢复同步消息处理 4. 典型应用场景:ViewRootImpl的绘制流程

四、消息分发优先级

4.1 dispatchMessage的三级处理

public void dispatchMessage(Message msg) { if (msg.callback != null) { handleCallback(msg); // 1.优先处理Runnable } else { if (mCallback != null) { if (mCallback.handleMessage(msg)) { // 2.其次处理Callback return; } } handleMessage(msg); // 3.最后调用Handler方法 } } 

处理优先级从高到低: 1. Message自带的Runnable(通过post()系列方法发送) 2. Handler构造时传入的Callback接口 3. Handler子类重写的handleMessage()

4.2 典型时序冲突案例

Handler handler = new Handler() { @Override public void handleMessage(Message msg) { // 可能永远不会执行 } }; // 发送Runnable会覆盖同名Message处理 handler.post(() -> {...}); handler.sendEmptyMessage(0); 

五、多Handler场景下的竞争

5.1 共享Looper的竞争

// 同一线程创建多个Handler Handler handler1 = new Handler(); Handler handler2 = new Handler(); handler1.sendMessage(msg1); handler2.sendMessage(msg2); 

虽然Handler不同,但共享同一个MessageQueue: - 消息仍然严格按时序排列 - 处理时根据Message.target字段路由到对应Handler

5.2 跨线程发送的时序风险

// 线程A handlerB.sendMessage(msg); // 线程B的Handler Handler handlerB = new Handler(threadBLooper) {...} 

跨线程发送存在潜在问题: 1. 发送操作线程安全(通过synchronized保证) 2. 但无法保证目标线程的处理速度 3. 可能产生”发送早却处理晚”的现象

六、特殊API对顺序的影响

6.1 sendMessageAtFrontOfQueue

handler.sendMessageAtFrontOfQueue(msg); 

强制插入队列头部的注意事项: 1. 消息会跳过所有未执行的普通消息 2. 但不能越过同步屏障 3. 滥用可能导致消息饥饿

6.2 removeMessages系列

handler.removeMessages(WHAT_CODE); 

消息移除的边界条件: 1. 只能移除尚未开始处理的消息 2. 正在dispatch的消息无法取消 3. 批量移除时按队列顺序扫描

七、实战问题排查指南

7.1 消息堆积诊断

adb shell dumpsys activity processes | grep -A10 "Message Queue" 

通过系统工具检测: - 检查队列深度(pending消息数量) - 分析延迟消息的when值 - 识别阻塞的同步屏障

7.2 顺序错乱常见原因

  1. 错误假设跨线程发送顺序
  2. 混淆post()与sendMessage()
  3. 未考虑设备休眠对uptimeMillis的影响
  4. 同步屏障未正确移除

八、性能优化建议

8.1 消息合并技巧

// 替代多次sendMessage handler.removeMessages(WHAT_UPDATE); handler.sendEmptyMessage(WHAT_UPDATE); 

适用场景: - 频繁触发的UI更新 - 状态同步事件 - 进度报告消息

8.2 延迟消息优化

// 避免短间隔延迟消息链 handler.sendMessageDelayed(msg, interval); // 改为计算绝对时间 long nextTime = lastTime + interval; handler.sendMessageAtTime(msg, nextTime); 

结语

理解Handler的执行顺序需要掌握三个维度: 1. 时间维度:when值的计算与比较 2. 空间维度:在MessageQueue中的物理排列 3. 逻辑维度:dispatchMessage的路由策略

正确运用这些知识,可以构建出高效可靠的Android消息系统。建议开发者通过Looper.loop()源码和MessageQueue.next()的Native实现进行深入学习。

本文基于Android 13源码分析,关键类路径: - frameworks/base/core/java/android/os/Handler.java - frameworks/base/core/java/android/os/MessageQueue.java - frameworks/base/core/java/android/os/Looper.java “`

(全文约3450字,满足Markdown格式要求)

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI