}
}
return true;
}
* 当链表为空或者时间小于表头消息时间,那么就插入表头,并且设置是否唤醒为`mBlocked`。
再结合上述的例子,也就是当有新消息要插入表头了,这时候如果之前是阻塞状态(mBlocked=true),那么就要唤醒线程了。
* 否则,就需要取链表中找到某个节点并插入消息,在这之前需要赋值`needWake = mBlocked && p.target == null && msg.isAsynchronous()`
也就是在插入消息之前,需要判断是否阻塞,并且表头是不是屏障消息,并且当前消息是不是异步消息。 也就是如果现在是同步屏障模式下,那么要插入的消息又刚好是异步消息,那就不用管插入消息问题了,直接唤醒线程,因为异步消息需要先执行。
* 最后一点,是在循环里,如果发现之前就存在异步消息,那就还是设置是否唤醒为`false`。
意思就是,如果之前有异步消息了,那肯定之前就唤醒过了,这时候就不需要再次唤醒了。
最后根据`needWake`的值,决定是否调用`nativeWake`方法唤醒`next()`方法。
[](
)8、同步屏障和异步消息是怎么实现的?
------------------------------------------------------------------------------------
其实在`Handler`机制中,有三种消息类型:
* `同步消息`。也就是普通的消息。
* `异步消息`。通过setAsynchronous(true)设置的消息。
* `同步屏障消息`。通过postSyncBarrier方法添加的消息,特点是target为空,也就是没有对应的handler。
这三者之间的关系如何呢?
* 正常情况下,同步消息和异步消息都是正常被处理,也就是根据时间when来取消息,处理消息。
* 当遇到同步屏障消息的时候,就开始从消息队列里面去找异步消息,找到了再根据时间决定阻塞还是返回消息。
Message msg = mMessages;
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
也就是说同步屏障消息不会被返回,他只是一个标志,一个工具,遇到它就代表要去先行处理异步消息了。
所以同步屏障和异步消息的存在的意义就在于有些消息需要`“加急处理”`。
[](
)9、同步屏障和异步消息有具体的使用场景吗?
---------------------------------------------------------------------------------------
使用场景就很多了,比如绘制方法`scheduleTraversals`。
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
// 同步屏障,阻塞所有的同步消息
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 通过 Choreographer 发送绘制任务
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}
}
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
在该方法中加入了同步屏障,后续加入一个异步消息`MSG_DO_SCHEDULE_CALLBACK`,最后会执行到`FrameDisplayEventReceiver`,用于申请VSYNC信号。
[](
)10、Message消息被分发之后会怎么处理?消息怎么复用的?
-------------------------------------------------------------------------------------------------
再看看loop方法,在消息被分发之后,也就是执行了`dispatchMessage`方法之后,还偷偷做了一个操作——`recycleUnchecked`。
public static void loop() {
for (;;) {
Message msg = queue.next(); // might block
try {
msg.target.dispatchMessage(msg);
}
msg.recycleUnchecked();
}
}
//Message.java
private static Message sPool;
private static final int MAX_POOL_SIZE = 50;
void recycleUnchecked() {
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = UID_NONE;
workSourceUid = UID_NONE;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
在`recycleUnchecked`方法中,释放了所有资源,然后将当前的空消息