在 Android 系统中的 Handler 机制 中 , 涉及到了 Handler , Message , Looper , MessageQueue 等组件 , 其中 MessageQueue 是消息队列 , 其中包含了很多 单链表 元素 ;
MessageQueue 源码地址 : https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/os/MessageQueue.java
Message 源码地址 : https://www.androidos.net.cn/android/9.0.0_r8/xref/frameworks/base/core/java/android/os/Message.java
在 Message 消息的源码中 , 包含了 Message next 指针 , 指向单链表中的下一个 Message 节点 ;
// sometimes we store linked lists of these things
/*package*/ Message next;
参考源码 : android/os/Message.java#115
在 MessageQueue 消息队列 中的 boolean enqueueMessage(Message msg, long when) 函数 是 向 消息队列 中添加 Message 消息的方法 ;
该函数的作用是 在 long when 时间后 , 执行 Message msg 消息 ;
添加 Message msg 消息时 , 需要参考 long when 时间参数 , 时间越长 Message 排序越靠后 , 时间越短 Message 的位置越靠前 ;
MessageQueue 消息队列 , 是 按照执行时间进行排序的 ;
在下面的代码逻辑中 , 一直进行死循环 , 判断当前的 Message 节点指针 p 指向的节点 , 如果该节点的时间小于传入的 long when 时间参数 , 那么找到了该节点 , 循环结束 , 插入节点 ;
插入节点的操作 , 只需要两行代码 , 改变指针的指向即可 , msg.next = p; prev.next = msg;
该 MessageQueue 几乎不需要查询遍历 , 但是会 频繁进行插入操作 , 因此在该场景下 , 使用单链表是最佳选择 ;
大部分情况下 , Handler 发送 Message 都会将 Message 消息插入到 Looper 中的 MessageQueue 的最前面 , 如果要使用顺序表 , 则每次插入 , 都需要挪动整个顺序表中的元素 ;
// 插入到队列的中间。通常我们不需要唤醒事件队列,
// 除非在队列的头部有一个障碍,并且该消息是队列中最早的异步消息。
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
// 插入 Message 节点
msg.next = p; // invariant: p == prev.next
prev.next = msg;
参考源码 : android/os/MessageQueue.java#564
在 MessageQueue 消息队列 中的 Message next() 函数 , 就是从 MessageQueue 消息队列中取出消息 , 并处理消息的函数 ;
Message next 函数位置 : android/os/MessageQueue.java#326
直接调用 msg = msg.next; 获取下一条消息 , 获取消息后 , 判定该消息的执行时间是否到了 , now < msg.when , 如果时间到了 , 就执行该消息 , 如果时间没有到 , 则设置超时唤醒 ;
// 尝试检索下一条消息。如果找到,返回。
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
if (msg != null && msg.target == null) {
// 被障碍物阻挡的。查找队列中的下一个异步消息。
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
if (msg != null) {
if (now < msg.when) {
// 下一条消息尚未准备好。设置一个超时唤醒当它准备好了。
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// 没有更多的信息。
nextPollTimeoutMillis = -1;
}