插入代码
public int postSyncBarrier() {
return postSyncBarrier(SystemClock.uptimeMillis());
}
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++;
final Message msg = Message.obtain();
msg.markInUse();
msg.when = when;
msg.arg1 = token;
Message prev = null;
Message p = mMessages;
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
if (prev != null) { // invariant: p == prev.next
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
return token;
}
}
从贴出的 postSyncBarrier(long when) 方法来看,同步屏障的插入位置取决于 when 参数的值,也就是屏障的触发时间。
来看关键代码:
Message prev = null;
Message p = mMessages;
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
if (prev != null) { // invariant: p == prev.next
msg.next = p;
prev.next = msg;
} else {
msg.next = p;
mMessages = msg;
}
结论
同步屏障被插入到 按照 when 时间排序的位置,也就是 整个消息链表中基于时间的合适位置。所以它既不是总在头部也不是总在尾部,而是:
• 如果 when = 0(默认值不是 0),则插入到 消息队列的最前面(头部);
• 如果 when > 0(比如当前时间),则按时间顺序插入到对应位置,可能在头、中或尾部。
举个例子:
如果当前 MessageQueue 中是如下链表:
Message1 (when=1000)
Message2 (when=1050)
Message3 (when=1100)
你调用 postSyncBarrier(SystemClock.uptimeMillis()) 假设当前时间是 1040,则 Barrier 会插入在 Message1 和 Message2 之间。