1.调用postSyncBarrier插入target为null的Message
这种消息为屏障消息,返回token,通过token可以移除这个屏障消息
public final class MessageQueue {
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++;
//创建的Message target为null
final Message msg = Message.obtain();
msg.markInUse(); //放入链表之前
msg.when = when;
msg.arg1 = token;
Message prev = null;
Message p = mMessages;
//在链表里,替when找到合适的位置
if (when != 0) {
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
}
//prev p(p要不然为null,要不然p的when大于when)
if (prev != null) { // invariant: p == prev.next
//prev msg p:msg放在prev和p之间
msg.next = p;
prev.next = msg;
} else {
//msg放到表头
msg.next = p;
mMessages = msg;
}
return token;
}
}
}
2.通过Message.next取出异步消息(isAsynchronous()为true)
在获得下一个要处理的Message的时候,如果MessageQueue有屏障消息,那就会pass掉!isAsynchronous()的消息,获得异步消息,对异步消息进行处理。
public final class MessageQueue {
Message next() {
for (;;) {
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//如果表头的target为null(屏障消息)
if (msg != null && msg.target == null) {//如果表头消息的target为null
// Stalled by a barrier. Find the
//next asynchronous message in the queue.
//遍历,跳过!isAsynchronous()的消息
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
//msg 为null或者msg的isAsynchronous为true时跳出循环
//也就是说如果有屏障消息,那这里的msg要么为null,要么是异步消息
//如果没有屏障消息,那这里的msg就是表头
if (msg != null) {
if (now < msg.when) {//当前时间小于msg的when
// Next message is not ready. Set a timeout
//to wake up when it is ready.
nextPollTimeoutMillis = (int) Math.min(msg.when - now,
Integer.MAX_VALUE);
} else {
// Got a message.
mBlocked = false;
//prevMsg msg msg.next
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next; //更新表头
}
msg.next = null;
msg.markInUse(); //next()返回消息之前调用markInUse
return msg;
}
} else {
//没有消息
// No more messages.
nextPollTimeoutMillis = -1;
}
}
}
}
}
3.removeSyncBarrier移除屏障消息
根据token找到对应的屏障消息,从链表移除,对这个Message进行回收
public final class MessageQueue {
public void removeSyncBarrier(int token) {
// Remove a sync barrier token from the queue.
// If the queue is no longer stalled by a barrier then wake it.
synchronized (this) {
Message prev = null;
Message p = mMessages;
//找target为null且arg1为token
while (p != null && (p.target != null || p.arg1 != token)) {
prev = p;
p = p.next;
}
if (p == null) {
throw new IllegalStateException("The specified message queue " +
"synchronization barrier token has not been posted or " +
+ "has already been removed.");
}
final boolean needWake;
if (prev != null) {//prev有值
prev.next = p.next;
needWake = false;
} else {
mMessages = p.next;
//没有消息或者链表头的target不为null
needWake = mMessages == null || mMessages.target != null;
}
p.recycleUnchecked(); //回收p
// If the loop is quitting then it is already awake.
// We can assume mPtr != 0 when mQuitting is false.
if (needWake && !mQuitting) {
nativeWake(mPtr);
}
}
}
}