booleanenqueueMessage(Message msg, longwhen) {
if (msg.isInUse()) {
thrownewAndroidRuntimeException(msg + " This message is already in use.");
}
if (msg.target == null) {
thrownewAndroidRuntimeException("Message must have a target.");
}
boolean needWake;
synchronized (this) {
if (mQuiting) {
RuntimeExceptione=newRuntimeException(
msg.target + " sending message to a Handler on a dead thread");
Log.w("MessageQueue", e.getMessage(), e);
returnfalse;
}
msg.when = when;
Messagep= mMessages;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
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;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
}
if (needWake) {
nativeWake(mPtr);
}
returntrue;
}
从 enqueueMessage 的实现来看,主要操作就是单链表的插入操作。接下来查看 next 方法的实现:
Message next() {
// Return here if the message loop has already quit and been disposed.finallongptr= mPtr;
if (ptr == 0) {
returnnull;
}
intpendingIdleHandlerCount= -1; // -1 only during first iterationintnextPollTimeoutMillis=0;
for (;;) {
if (nextPollTimeoutMillis != 0) {
Binder.flushPendingCommands();
}
nativePollOnce(ptr, nextPollTimeoutMillis);
synchronized (this) {
// Try to retrieve the next message. Return if found.finallongnow= SystemClock.uptimeMillis();
MessageprevMsg=null;
Messagemsg= mMessages;
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 (msg != null && !msg.isAsynchronous());
}
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 {
// Got a message.
mBlocked = false;
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 {
// No more messages.
nextPollTimeoutMillis = -1;
}
// Process the quit message now that all pending messages have been handled.if (mQuitting) {
dispose();
returnnull;
}
// If first time idle, then get the number of idlers to run.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 = newIdleHandler[Math.max(pendingIdleHandlerCount, 4)];
}
mPendingIdleHandlers = mIdleHandlers.toArray(mPendingIdleHandlers);
// Run the idle handlers.for (inti=0; i < pendingIdleHandlerCount; i++) {
finalIdleHandleridler= mPendingIdleHandlers[i];
mPendingIdleHandlers[i] = null; // release the reference to the handlerbooleankeep=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;
}
}
}
相信大家一定有遇到过,在子线程中创建 Handler 会报错。解决办法就是 new Handler 的时候加上 Looper.prepare()。而 Looper.prepare() 的内部实现逻辑就是创建一个 Looper:
publicstaticvoidprepare() {
prepare(true);
}
privatestaticvoidprepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
thrownewRuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(newLooper(quitAllowed));
}
publicstaticvoidloop() {
finalLooperme= myLooper();
if (me == null) {
thrownewRuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
finalMessageQueuequeue= me.mQueue;
// Make sure the identity of this thread is that of the local process,// and keep track of what that identity token actually is.
Binder.clearCallingIdentity();
finallongident= Binder.clearCallingIdentity();
for (;;) {
Messagemsg= queue.next(); // might blockif (msg == null) {
// No message indicates that the message queue is quitting.return;
}
// This must be in a local variable, in case a UI event sets the loggerfinalPrinterlogging= me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
finallongtraceTag= me.mTraceTag;
if (traceTag != 0) {
Trace.traceBegin(traceTag, msg.target.getTraceName(msg));
}
try {
msg.target.dispatchMessage(msg);
} finally {
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
if (logging != null) {
logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
}
// Make sure that during the course of dispatching the// identity of the thread wasn't corrupted.finallongnewIdent= Binder.clearCallingIdentity();
if (ident != newIdent) {
Log.wtf(TAG, "Thread identity changed from 0x" +
Long.toHexString(ident) + " to 0x" +
Long.toHexString(newIdent) + " while dispatching to " + msg.target.getClass().getName() + " " + msg.callback + " what=" + msg.what);
}
msg.recycleUnchecked();
}
}
通过代码我们知道:looper 方法是一个死循环,唯一跳出的循环的方式是 MessageQueue 的 next 方法返回 null,但这几乎不可能,因为在 MessageQueue 的 next 方法中,假如没有消息加入队列,next 方法会一直阻塞,不会返回 null。如果我们不手动调用 quit 或者 quitSafely 方法的话,MessageQueue 的 next 方法是不可能返回 null 的。当 MessageQueue 没有消息时,next 方法会一直阻塞在那里,因为 MessageQueue 的 next 方法阻塞了,就导致 Looper 的 loop 方法也一直在阻塞了。