为了让View能够有快速的布局和绘制,android中定义了一个Barrier的概念,当View在绘制和布局时会向Looper中添加了Barrier(监控器),这样后续的消息队列中的同步的消息将不会被执行,以免会影响到UI绘制,但是只有异步消息才能被执行。 所谓的异步消息也只是体现在这,添加了Barrier后,消息还可以继续被执行,不会被推迟运行。 如何使用异步消息,只有在创建Handler(构造方法的参数上标识是否异步消息)的时候或者在发送Message(Mesasge#setAsynchronous(true))时进行设置。而异步消息应用层是无法设置,因为相关设置的方法均是Hide的。
两种方式可以发送异步消息
1.在创建Handler时,在构造方法上传递参数true就可以,如下:
public Handler(Callback callback, boolean async) {
...
mAsynchronous = async;
}
在Handler上设置异步的话,那么使用此Handler发送的消息都将被设置Mesasge#setAsynchronous(true)
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
Message#setAsynchronous去设置,但是也是Hide的。
/**
* Sets whether the message is asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with represent to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param async True if the message is asynchronous.
*
* @see #isAsynchronous()
* @see MessageQueue#enqueueSyncBarrier(long)
* @see MessageQueue#removeSyncBarrier(int)
*
* @hide
*/
public void setAsynchronous(boolean async) {
if (async) {
flags |= FLAG_ASYNCHRONOUS;
} else {
flags &= ~FLAG_ASYNCHRONOUS;
}
}
当ViewRootImpl开始measure和layout ViewTree时,会向主线程的Handler添加Barrier
void scheduleTraversals() {
if (!mTraversalScheduled) {
mTraversalScheduled = true;
mTraversalBarrier = mHandler.getLooper().postSyncBarrier();
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
scheduleConsumeBatchedInput();
}
}
void unscheduleTraversals() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
mHandler.getLooper().removeSyncBarrier(mTraversalBarrier);
mChoreographer.removeCallbacks(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
}