1.Handler的工作流程( 四 )


这个if判断中
如果消息队列为空(即没有已存在的消息),
如果当前消息的触发时间为 0(即立即触发),
如果当前消息的触发时间早于消息队列中已有消息的触发时间
那么就将当前消息的 next 属性指向原先的队头 p , 即将当前消息插入到原先的队头之前 。
将队列的头部指针更新为当前消息 , 使其成为新的队头 。
根据当前线程的阻塞状态来设置变量 。如果当前线程被阻塞(即等待消息队列) , 则需要唤醒线程 , 以便立即处理新插入的消息 。
然后在else中
for (;;) {prev = p;p = p.next;if (p == null || when < p.when) {break;}if (needWake && p.isAsynchronous()) {needWake = false;}}msg.next = p; // invariant: p == prev.nextprev.next = msg;
如果在==true且当前的插入为异步操作,则取消唤醒
如果没有插入的东西或者当前消息的触发时间早于消息队列中已有消息的触发时间则退出for循环
否则的话就一直进入for循环进行插入操作
2..()
我们点击()的源码
public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {return sendMessageDelayed(getPostMessage(r), delayMillis);}/** @hide */public final boolean postDelayed(Runnable r, int what, long delayMillis) {return sendMessageDelayed(getPostMessage(r).setWhat(what), delayMillis);}
我们会发现其实post()和()内部是一样的,都调用的(),所以两个唯一的不同就是,post里面传递的为0,而()传递的不一定为0
2.4.1注意: 1.的延迟消息
的延迟消息是确定的吗?  , 后续修改系统时间会影响延迟消息吗?
这个回答我们可以看看
()中的源码
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
中注意:
SystemClock.uptimeMillis() + delayMillis
.() +是用来计算相对时间的表达式 。它的目的是计算出延迟触发的时间点 。
.() 是一个用于获取系统启动时间的方法 , 它返回自系统启动以来经过的毫秒数 。它不受系统时间的修改影响 。
是延迟的时间间隔 , 以毫秒为单位 。
通过将当前的系统启动时间(.())与延迟的时间间隔()相加 , 可以得到延迟触发的时间点 。
如果我(2000)的话,就有可能延迟超过了 。因为的时间为.() +
但是消息延迟不单单因为这个
在系统中 , 处理消息和执行任务的机制是基于消息循环( Loop)和系统调度 。延迟消息的触发时间取决于消息队列中的其他消息、正在执行的任务、系统负载等因素 。
因此 , 尽管你指定了2000毫秒的延迟 , 但实际触发时间可能会稍有偏差 , 可能略早或略晚于2000毫秒 。
另外 , 需要注意的是 , 系统事件(例如屏幕休眠、设备进入深度睡眠模式等)也可能会影响到延迟消息的触发时间 , 因为在这些事件发生时 , 消息循环可能会被暂停或受到影响 。
后续修改系统时间并不会影响延迟消息,因为我延迟消息本来就和系统时间没有关系,
.() 是一个用于获取系统启动时间的方法 , 它返回自系统启动以来经过的毫秒数 。它不受系统时间的修改影响 。
简单总结一下上面的话:的延迟消息不是确定的, 可能时间超过或小于
因为2点:
处理消息和执行任务的机制是基于消息循环( Loop)和系统调度 。延迟消息的触发时间取决于消息队列中的其他消息、正在执行的任务、系统负载等因素 。系统事件(例如屏幕休眠、设备进入深度睡眠模式等)也可能会影响到延迟消息的触发时间 , 因为在这些事件发生时 , 消息循环可能会被暂停或受到影响 。