Handler中MessageQueue的enqueueMessage笔记

本文深入探讨了Android中Handler的消息机制,详细分析了MessageQueue的工作原理,特别是消息入队的实现方式,帮助读者更好地理解Handler的工作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天心血来潮,又默默的想着Handler的实现原理,毕竟面试这个可是热门的话题,虽然看了很多遍源码,但每次都是研究Loop和Handler的关系,今天看着看着进到MessageQueue的源码里,了解了下把Message入队的操作,分享给大家。

首先我们先看Message类,根据名字我们可以知道它是消息的意思,我们每次调用handler.post(Runnable)系统都会调用getPostMessage方法 转换成一个Message,它内部有个变量next,它的类型也是Message,数据结构基础好的童鞋应该会反应过来,没错Message类似于一个链表结构。


进入正题先看enqueueMessage部分源码:

boolean enqueueMessage(Message msg, long when) {
msg.when = when;
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
boolean needWake;
msg.next = p;
// New head, wake up the event queue if blocked.
mMessages = msg;
// Inserted within the middle of the queue. Usually we don't have to wake
needWake = mBlocked;
} else {
// and the message is the earliest asynchronous message in the queue.
// up the event queue unless there is a barrier at the head of the queue
p = p.next;
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
msg.next = p; // invariant: p == prev.next
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p;
prev.next = msg;
}


参数msg是由我们传进去的Runnable转换成的对象,when时是执行时间,当我们调handler.post 时该值为0,细心的朋友会发现mMessages这个对象,我们可以把它理解为是待执行的message队列,该队列是按照when的时间排序的且第一个消息是最先执行。

代码中第4行中有三个条件:如果mMessages对象为空,或者when为0也就是立刻执行,或者新消息的when时间比mMessages队列的when时间还要早,符合以上一个条件就把新的msg插到mMessages的前面 并把next指向它,也就是msg会插进上图中队列的最前面,等待loop的轮询。

如果上面的条件都不符合就进入else代码中,我们可以看到17行是有个for的死循环遍历已有的message对象,其中第20行中有个if语句when < p.when when是新消息的执行时间,p.when的是队列中message消息的执行时间,如果找到比新的message还要晚执行的消息,就执行
msg.next = p;
prev.next = msg;
也就是把插到该消息的前面,优先执行新的消息。

到这里,这个消息队列的入队规则就讲完了,蛮简单的,如果有面试官问到这个我们一定要流利的说出来。



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值