Android 消息机制深入源码分析 [ 一 ]
Android 消息机制之 ThreadLocal 深入源码分析 [ 二 ]
Android 消息机制之 Looper 深入源码分析 [ 三 ]
Android 消息机制之 Message 与消息对象池的深入源码分析 [ 四 ]
Android 消息机制之 MessageQueue 深入源码分析 [ 五 ]
Android 消息机制之初识Handler [ 六 ]
Android 消息机制之 Handler 发送消息的深入源码分析 [ 七 ]
Android 消息机制之 MessageQueue.next() 消息取出的深入源码分析 [ 八 ]
Android 消息机制之消息的其他处理深入源码分析 [ 九 ]
Android 消息机制总结 [ 十 ]
紧接上一章消息的发送, 本章内容为消息的取出分析学习.
消息的取出主要是通过 Looper
的 loop
方法. 这个方法在第三章的时候已经分析过, 分为以下几步
- 获取
Looper
对象 - 获取
MessageQueue
消息队列对象 - 死循环遍历
- 通过
queue.next()
来从MessageQueue
的消息队列中获取一个Message msg
对象 - 通过
msg.target
,dispatchMessage(msg)
来处理消息 - 通过
msg.recycleUnchecked()
方法来回收Message
到消息对象池中.
其中 Message.recycleUnchecked()
在第四章的时候已经分析过, 那么现在就剩下 MessageQueue.next()
与 handler.dispatchMessage()
. 那么先来看 MessageQueue.next()
1. MessageQueue.next()
MessageQueue.java 310 行, 代码过多, 将分段分析.
Message next() {
//分析 1
final long ptr = mPtr;
if (ptr == 0) {
return null;
}
//分析 2
int pendingIdleHandlerCount = -1; // -1 only during first iteration
//分析 3
int nextPollTimeoutMillis = 0;
- 分析:
//分析 4
for (;;) {
//分析 5
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
//分析 6
nativePollOnce(ptr, nextPollTimeoutMillis);
//分析 7
synchronized (this) {
final long now = SystemClock.uptimeMillis();
Message prevMsg = null;
Message msg = mMessages;
//分析 8
if (msg != null && msg.target == null) {
do {
prevMsg = msg;
msg = msg.next;
} while (msg != null && !msg.isAsynchronous());
}
- 分析
//分析 9
if (msg != null) {
//分析 10
if (now < msg.when) {
nextPollTimeoutMillis = (int) Math.min(msg.when - now, Integer.MAX_VALUE);
} else { //分析 11
mBlocked = false;
//分析 12
if (prevMsg != null) {
prevMsg.next = msg.next;
} else {
mMessages = msg.next;
}
msg.next = null;
if (DEBUG) Log.v(TAG, "Returning message: " + msg);
msg.markInUse();
return msg;
}
} else {
//分析 13
nextPollTimeoutMillis = -1;
}
- 分析
//分析 14
if (mQuitting) {
dispose();
return null;
}
//分析 15
if (pendingIdleHandlerCount < 0 && (mMessages == null || now < mMessages.when)) {
pendingIdleHandlerCount = mIdleHandlers.size();
}
//分析 16
if (pendingIdleHandlerCount <= 0) {
// No idle handlers to run. Loop and wait some more.
mBlocked = true;
continue;
}
//分析 17
if (mPendingIdleHandlers == null) {
mPendingIdleHandlers = new IdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
}
注意: 当代码开始执行这里的时候, msg
要么为 null
, 要么未到执行时间.
- 分析
//分析18
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);
}
}
}
//分析 19
pendingIdleHandlerCount = 0;
//分析 20
nextPollTimeoutMillis = 0;
}
}
注意: 执行到这里, 说明目前没有可执行的 Message
, 但是有可以在空闲时执行的 IdleHandler
.
关于分析 18 的疑问. 为什么只会在第一次循环的时候会执行这里呢.
总结
总的来说当在 Looper.loop()
方法的死循环内, 调用MessageQueue.next()
方法获取一个 Message
的时候, 大致会分为以下几步.
好了, 本章分析学习就到这里结束了, 下一章将会分析学习 消息分发处理, 消息的移除, 以及消息的其他操作.