Handler源码分析之Message类型
创始人
2025-06-01 15:29:08
0

问:大家知道Handler机制中发送的Message分为几种吗?

答:分为 同步消息、屏障消息(消息屏障)、异步消息 这三种

同步消息

就是我们平时最常用的消息。

屏障消息

Message.target = null 的消息

理论依据:

MessageQueue.java//发送消息屏障private int postSyncBarrier(long when) {// Enqueue a new sync barrier token.// We don't need to wake the queue because the purpose of a barrier is to stall it.synchronized (this) {final int token = mNextBarrierToken++;//从message的复用池中获得一个messagefinal Message msg = Message.obtain();msg.markInUse();msg.when = when;msg.arg1 = token;Message prev = null;//mMessages 就是消息队列,单向链表结构Message p = mMessages;if (when != 0) {while (p != null && p.when <= when) {prev = p;p = p.next;}}if (prev != null) { // invariant: p == prev.nextmsg.next = p;prev.next = msg;} else {msg.next = p;mMessages = msg;}//可以看到将msg放入队列的过程中并没有给msg.target赋值即:msg.target = nullreturn token;}}而同步消息入队列时:Handler.javaprivate boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,long uptimeMillis) {//将发送消息的handler对象赋值给了msg.targetmsg.target = this;msg.workSourceUid = ThreadLocalWorkSource.getUid();if (mAsynchronous) {msg.setAsynchronous(true);}return queue.enqueueMessage(msg, uptimeMillis);}

那么为什么这么设计呢?因为对于屏障消息来说这个消息本身没有任何意义,发送这个消息不是用来跨线程通信的,它是不会像同步消息一样被分发的,它的作用是用来标识说我(此屏障消息)后面有异步消息需要尽快处理。所以它的使用场景是在发出异步消息前先发一个屏障消息,至于为什么要这样我们下面会分析。

异步消息

Message调用了setAsynchronous(true),即设置了Message.flag = FLAG_ASYNCHRONOUS的消息

那么问题来了,同步消息我们可以用来进行线程间通信,异步消息被设计出来是干什么的呢?

了解过android屏幕刷新机制的小伙伴会知道,屏幕的刷新频率一般是60Hz,即1秒中刷新60次约16.7ms刷新一次,以保证视觉上的连续性,人眼就不会感觉到卡顿。UI刷新也是通过handler机制来完成的。及系统会每隔16.7ms发送一个异步消息用于屏幕UI刷新。

空口无凭我们来看下源码:

研究过view的绘制流程的小伙伴知道,view刷新最终会调用到ViewRootImpl的scheduleTraversals():

void scheduleTraversals() {if (!mTraversalScheduled) {mTraversalScheduled = true;//这里先发送了一个屏障消息mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();//继续进入这个方法mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);notifyRendererOfFramePending();pokeDrawLockIfNeeded();}
}最终来到这个方法:
Choreographer.java
private void postCallbackDelayedInternal(int callbackType,Object action, Object token, long delayMillis) {...synchronized (mLock) {final long now = SystemClock.uptimeMillis();final long dueTime = now + delayMillis;mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token);if (dueTime <= now) {scheduleFrameLocked(now);} else {//这里发送了一个异步消息 (action就是上面传入的mTraversalRunnable)Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);msg.arg1 = callbackType;msg.setAsynchronous(true);//设置这个消息为异步消息mHandler.sendMessageAtTime(msg, dueTime);}}}

OK,到此三种类型消息的差异及用途我们就分析清楚了。

在此也需要提及一下的是,虽然构建三种类型的消息的细节上有一点差异,但三种类型的消息在进入队列的逻辑是一致的,都是根据比较时间来讲message插入到合适的位置,如下图:

但在取消息时有一定的差异,如下图:

队头是同步消息时,就是正常取出,比如将m1取出了,m2就成了队头,就这样取当取到m3时发现这个msg.target=null,就知道m3是一个屏障消息,取到它代表后面跟着一个急需处理的异步消息(UI刷新消息),那么就会一直往后找直到遍历到m5时发现它是异步消息,那就赶紧把m5先取出并分发它去执行UI刷新的逻辑(这里对应MessageQueue的next()方法中的逻辑),还记得上面mTraversalRunnable吗?它被赋值给了异步消息中obj这个成员变量随着Message一起被分发出去,当执行到这个Runnable任务时:

final TraversalRunnable mTraversalRunnable = new TraversalRunnable();
final class TraversalRunnable implements Runnable {@Overridepublic void run() {//走到这里doTraversal();}}void doTraversal() {if (mTraversalScheduled) {mTraversalScheduled = false;//在这里移除了屏障消息mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);if (mProfile) {Debug.startMethodTracing("ViewAncestor");}//这个方法非常眼熟,是开始View绘制三部曲(测量、布局、绘制)的入口performTraversals();if (mProfile) {Debug.stopMethodTracing();mProfile = false;}}}

所以,当分发了异步消息后,在取下一个消息前,这个屏障消息就被移除了。

相关内容

热门资讯

家装预付资金安全困局如何破解,... 家装预付资金安全困局如何破解 专家提出:建立“先验收后付款”装修资金存管制度 预交数万元甚至数十万元...
工行安康解放路支行积极开展《反... 为深入贯彻落实《国家金融监督管理总局安康监管分局办公室关于开展<反有组织犯罪法>宣传活动的通知》要求...
重庆公布育儿补贴制度实施方案 原标题:每孩每年3600元 重庆公布育儿补贴制度实施方案 11月21日,记者了解到,市卫生健康委、市...
十五运会组委会在深总结本届赛事... 深圳新闻网2025年11月22日讯(深圳报业集团记者 林炜航)11月21日,十五运会组委会在深圳市民...
中国军视网:日本妄言击沉福建舰... 本文转自【中国军视网】; 日本首相高市早苗发表涉台错误言论,公然挑战一个中国原则,甚至还有日本无知政...
重磅!东莞长安50万㎡产城发布... 在当下竞争激烈的市场环境中,中小企业如何突破成本压力,找到一片既能扎根成长又能眺望未来的理想栖息地?...
毕马威:政策、资本等多维着力 ... 由毕马威联合长三角G60科创走廊创新研究中心主办的“长三角高端装备新质领袖榜单发布仪式”于11月21...
河曲县开展驻村帮扶工作政策业务... 来源:河曲县融媒体中心 近日,我县组织开展驻村帮扶工作政策业务集中培训,进一步提升驻村帮扶干部...
羽绒服涨价与猪肉降价有关?经济... 中央气象台发布统计信息,14日至17日,我国今年下半年首轮大范围寒潮天气即将自西向东影响我国,多地降...
周勇,任上落马 11月21日,中央纪委国家监委网站发布通报: 国家能源集团乌海能源党委书记、董事长周勇涉嫌严重违纪违...