MessageQueue
private native static long nativeInit();
private native static void nativeDestroy(long ptr);
private native void nativePollOnce(long ptr, int timeoutMillis); /*non-static for callbacks*/
private native static void nativeWake(long ptr);
private native static boolean nativeIsPolling(long ptr);
private native static void nativeSetFileDescriptorEvents(long ptr, int fd, int events);
MessageQueue(boolean quitAllowed) {
mQuitAllowed = quitAllowed;
// mPtr c++层messagequeue指针
mPtr = nativeInit();
}
阻塞取消息next()
Message next() {
// Return here if the message loop has already quit and been disposed.
// This can happen if the application tries to restart a looper after quit
// which is not supported.
final long ptr = mPtr;
// 未初始化C++层messageQueue返回null消息
if (ptr == 0) {
return null;
}
int pendingIdleHandlerCount = -1; // -1 only during first iteration
int nextPollTimeoutMillis = 0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
// 阻塞nextPollTimeoutMillis超时,等待
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
// 当前第一个message target属性为null, 即该消息为同步屏障消 // 息, 将会优先获取异步消息 msg.isAsynchronous()
// 同步屏障消息只影响在它后面的异步消息
if (msg != null && msg.target == null) {
// Stalled by a barrier. Find the next asynchronous message in the queue.
do {
prevMsg = msg;
msg = msg.next;
// 当消息为异步消息时退出while循环
} while (msg != null && !msg.isAsynchronous());
}
// 获取的msg要么是同步屏障拦截遍历得到的队列第一个异步消息
// 要么就是mMessages, 即消息队列第一个消息
if (msg != null) {
// 如果当前获取的消息还没到时间, 设置一个超时时间等待唤 // 醒, 当前获取的消息肯定比该消息后面的消息时间小
// 消息进入队列的时候已经保证这点
if (now < 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 {
// 如果满足时间要求, 则该消息符合条件, 可处理
// 将该消息从队列中移除
// 如果该消息存在prevMsg,即前面有消息, 该消息前面
// 一个消息指向该消息下一个消息
// 如果不存在prevMsg, 则说明该消息是第一个 // mMessages 重新复值为该消息的下一个
// Got a message.
mBlocked = false;
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
// 清空该消息的next指针
// 标示该消息inUse, 防止复用
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
// No more messages.
// 消息队列没有消息, 超时时间为
// nextPollTimeoutMillis -1
nextPollTimeoutMillis = -1;
}
// 程序走到这里, 说明队列没有消息
// 处理IdleHandler
public static interface IdleHandler {
/**
* Called when the message queue has run out of messages and will now
* wait for more. Return true to keep your idle handler active, false
* to have it removed. This may be called if there are still messages
* pending in the queue, but they are all scheduled to be dispatched
* after the current time.
*/
boolean queueIdle();
}
// Process the quit message now that all pending messages have been handled.
if (mQuitting) {
dispose();
return null;
}
// If first time idle, then get the number of idlers to run.
// Idle handles only run if the queue is empty or if the first message
// in the queue (possibly a barrier) is due to be handled in the future.
if (pendingIdleHandlerCount < 0
&& (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
// Run the idle handlers.
// We only ever reach this code block during the first iteration.
for (int i = 0; i < pendingIdleHandlerCount; i++) {
final IdleHandler idler = mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handler
boolean keep = false;
try {
keep = idler.queueIdle();
} catch (Throwable t) {
Log.wtf(TAG, "IdleHandler threw exception", t);
}
if (!keep) {
synchronized (this) {
mIdleHandlers.remove(idler);
}
}
}
// Reset the idle handler count to 0 so we do not run them again.
pendingIdleHandlerCount = 0;
// While calling an idle handler, a new message could have been delivered
// so go back and look again for a pending message without waiting.
nextPollTimeoutMillis = 0;
}
}
enqueueMessage
boolean enqueueMessage(Message msg, long when) {
// target为null, 即同步屏障消息, 不允许该接口插入
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
// msg 在next方法中遍历得到之后会标示为inuse, 防止复用
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
// 该消息标识为inUse
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
// 如果队列消息头为null,
// 或者插入的消息时间为0, 即handler通过sendMessageAtFrontOfQueue接口插入队列头部的消息
// 或者该插入消息时间小于头部消息时间
// 则该消息成为队列头部消息,next指针指向原来队列头部信息
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
// 如果mBlocked true说明当前队列读取(next)已经阻塞,需要唤醒
// 如果mBlocked false即当前队列仍然被正常遍历获取消息中(next)
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
// 插入队列中间位置, 通常我们不需要唤醒, 插入中间显然没必要唤醒
// 除非插入的消息是异步消息而且, 当前头部消息为同步屏障消息
// 如果是该情况则需要唤醒,
// 但是如果该消息前面依旧有异步消息的话似乎也没必要唤醒, 因为前面的异步消息已经做了同样的判断操作
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
// 循环查找合适插入的位置, 要么是查找到队列尾部
// 要么是查找到合适的中间位置 when < p.when
if (p == null || when < p.when) {
break;
}
// 假如前面判断需要唤醒, 即mBlocked && p.target == null && msg.isAsynchronous() 为ture, 即插入的为异步消息
// 如果队列中存在时间比新插入的异步消息小的异步消息, 那么就没有必要唤醒
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
// 该插入消息位置在prev 和 p 之间
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
// 如果需要唤醒, 则通知
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
插入同步屏障, 保证同步屏障后面的异步消息优先处理
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;
}
}
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;
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.next = p.next;
needWake = false;
} else {
// 如果该屏障的位置是队列首部, 如果下一个消息target不为null, 需要唤醒
mMessages = p.next;
needWake = mMessages == null || mMessages.target != null;
}
// 回收该消息
p.recycleUnchecked();
// If the loop is quitting then it is already awake.
// We can assume mPtr != 0 when mQuitting is false.
// 唤醒
if (needWake && !mQuitting) {
nativeWake(mPtr);
}
}
}