handler的運(yùn)行離不開looper和messagequeen的支持,我們使用looper.prepare(looper.prepare(boolean quitAllowed))來創(chuàng)建一個looper,prepare方法中將創(chuàng)建的loopear存放到threadlocal(在指定的線程中存儲數(shù)據(jù),數(shù)據(jù)存儲后,只能在指定的線程中讀取)中,

在loopear的構(gòu)造方法中,會創(chuàng)建一個messageQueen,用來存放message,至此,looper的準(zhǔn)備工作已經(jīng)完成

當(dāng)我們調(diào)用looper.loop()方法時,會判斷l(xiāng)oopear有沒有初始化,沒有則拋出異常,拿到初始化的looper后,通過looper獲取lopper中創(chuàng)建的messageQueen,然后通過死循環(huán),不停的通過messageQueen.next()獲取消息,當(dāng)沒有消息時將會阻塞等待新消息入隊(duì),直到messageQueen.next()返回null時,結(jié)束循環(huán)。當(dāng)looper.loop方法中接收到消息時,會調(diào)用msg.target.dispatchMessage(msg);也就是handler的dispatchMessage(msg)方法,將消息交由handler處理,在Handler中會通過looper.myLooper()獲取looper,在handler調(diào)用sendMessage(Message msg)方法時,會將message通過queue.enqueueMessage(msg, uptimeMillis);放入MessageQueen中,喚醒looper.loop的阻塞等待,進(jìn)行后續(xù)處理。
public boolean sendMessageAtTime(Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
// 將message放入messageQueen `方法內(nèi)部調(diào)用queue.enqueueMessage(msg, uptimeMillis);`
return enqueueMessage(queue, msg, uptimeMillis);
}
-
looper.loop()
public static void loop() { //判斷l(xiāng)ooper有沒有初始化 final Looper me = myLooper(); if (me == null) { throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."); } final MessageQueue queue = 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(); final long ident = Binder.clearCallingIdentity(); // Allow overriding a threshold with a system prop. e.g. // adb shell 'setprop log.looper.1000.main.slow 1 && stop && start' final int thresholdOverride = SystemProperties.getInt("log.looper." + Process.myUid() + "." + Thread.currentThread().getName() + ".slow", 0); boolean slowDeliveryDetected = false; for (;;) { Message msg = queue.next(); // might block if (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 logger final Printer logging = me.mLogging; if (logging != null) { logging.println(">>>>> Dispatching to " + msg.target + " " + msg.callback + ": " + msg.what); } final long traceTag = me.mTraceTag; long slowDispatchThresholdMs = me.mSlowDispatchThresholdMs; long slowDeliveryThresholdMs = me.mSlowDeliveryThresholdMs; if (thresholdOverride > 0) { slowDispatchThresholdMs = thresholdOverride; slowDeliveryThresholdMs = thresholdOverride; } final boolean logSlowDelivery = (slowDeliveryThresholdMs > 0) && (msg.when > 0); final boolean logSlowDispatch = (slowDispatchThresholdMs > 0); final boolean needStartTime = logSlowDelivery || logSlowDispatch; final boolean needEndTime = logSlowDispatch; if (traceTag != 0 && Trace.isTagEnabled(traceTag)) { Trace.traceBegin(traceTag, msg.target.getTraceName(msg)); } final long dispatchStart = needStartTime ? SystemClock.uptimeMillis() : 0; final long dispatchEnd; try { msg.target.dispatchMessage(msg); dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0; } finally { if (traceTag != 0) { Trace.traceEnd(traceTag); } } if (logSlowDelivery) { if (slowDeliveryDetected) { if ((dispatchStart - msg.when) <= 10) { Slog.w(TAG, "Drained"); slowDeliveryDetected = false; } } else { if (showSlowLog(slowDeliveryThresholdMs, msg.when, dispatchStart, "delivery", msg)) { // Once we write a slow delivery log, suppress until the queue drains. slowDeliveryDetected = true; } } } if (logSlowDispatch) { showSlowLog(slowDispatchThresholdMs, dispatchStart, dispatchEnd, "dispatch", msg); } 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. final long newIdent = 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(); }}