你真的了解Android的Handler機(jī)制嗎?

在Android系統(tǒng)中,Handler機(jī)制應(yīng)用較廣,尤其是在App層面,基本每個(gè)App都會用到。使用的場景主要是向主線程發(fā)送事件,更新UI。但大家真的了解Handler機(jī)制嗎?看一下面的幾個(gè)問題是否可以回答:

a.Handler是如何實(shí)現(xiàn)多個(gè)線程之前事件傳遞的?

b.Handler、Message、MessageQueue、Looper相互之間的數(shù)量比是多少,都是1:1嗎?

c.每個(gè)變量運(yùn)行的線程是那個(gè)?

d.ThreadLocal是怎么回事,在Handler機(jī)制中起什么作用?

能準(zhǔn)確回答上述問題,說明對Handler機(jī)制的理解已相當(dāng)?shù)轿涣恕?/p>

一、下面論述一下Handler機(jī)制各類的實(shí)現(xiàn)原理,從而揭露內(nèi)部的工作流程。(源碼環(huán)境為Android8.0)

1. 先來看Handler類:

1.1 構(gòu)造方法:

Handler的構(gòu)造方法總共有如下幾個(gè),最終實(shí)現(xiàn)為下面兩個(gè)方法:

public Handler(Callback callback, boolean async) {

? ? if (FIND_POTENTIAL_LEAKS) {

? ? ? ? final Class klass = getClass();

? ? ? ? if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) &&

? ? ? ? ? ? ? ? (klass.getModifiers() & Modifier.STATIC) == 0) {

? ? ? ? ? ? Log.w(TAG, "The following Handler class should be static or leaks might occur: " +

? ? ? ? ? ? ? ? klass.getCanonicalName());

? ? ? ? }

? ? }

? ? mLooper = Looper.myLooper();

? ? if (mLooper == null) {

? ? ? ? throw new RuntimeException(

? ? ? ? ? ? "Can't create handler inside thread that has not called Looper.prepare()");

? ? }

? ? mQueue = mLooper.mQueue;

? ? mCallback = callback;

? ? mAsynchronous = async;

}

public Handler(Looper looper, Callback callback, boolean async) {

? ? mLooper = looper;

? ? mQueue = looper.mQueue;

? ? mCallback = callback;

? ? mAsynchronous = async;

}

最終都調(diào)至Handler(Callback callback, boolean async)和Handler(Looper looper, Callback callback, boolean async),看一下源碼可知,主要為初始化幾個(gè)變量:mLooper、mQueue、mCallback,mAsynchronous,前三個(gè)變量非常重要,有以下幾個(gè)結(jié)論:

a.一個(gè)Handler中含有一個(gè)Looper

b.Handler中持有的MessageQueue源于Looper中,與Looper中該變量行為一致

c.一個(gè)Handler中含有一個(gè)Callback

Handler中還有如下幾個(gè)重要的方法,提供了Handler對外的能力:

1.2 obtainMessage方法,對外提供一個(gè)獲取Message緩存池中Message的方法,避免應(yīng)用產(chǎn)生過多的Message對象。根據(jù)參數(shù)的不同,重載有多個(gè)該方法,實(shí)現(xiàn)原理都一樣,以其中之一分析一下:

//obtainMessage@Handler.java

public final Message obtainMessage()

{

? ? return Message.obtain(this);

}

//obtain@Message.java

public static Message obtain(Handler h) {

? ? Message m = obtain();

? ? m.target = h;

? ? return m;

}

// obtain@Message.java

public static Message obtain() {

? ? synchronized (sPoolSync) {

? ? ? ? if (sPool != null) {

? ? ? ? ? ? Message m = sPool;

? ? ? ? ? ? sPool = m.next;

? ? ? ? ? ? m.next = null;

? ? ? ? ? ? m.flags = 0; // clear in-use flag

? ? ? ? ? ? sPoolSize--;

? ? ? ? ? ? return m;

? ? ? ? }

? ? }

? ? return new Message();

}

sPool提供復(fù)用功能的實(shí)現(xiàn),其存儲結(jié)構(gòu)為鏈表,通過sPoolSize的大小及SPool頭部指針位置作到這一點(diǎn),感興趣的同學(xué)可以研究下

1.3 post方法、sendMessage方法,Handler提供了多個(gè)post方法,按參數(shù)不同,提供了諸如指定時(shí)間、延時(shí)的功能,基本功能是一樣的,以其中某一個(gè)方法說一下其實(shí)現(xiàn):

public final boolean post(Runnable r)

{

? return? sendMessageDelayed(getPostMessage(r), 0);

}

private static Message getPostMessage(Runnable r) {

? ? Message m = Message.obtain();

? ? m.callback = r;

? ? return m;

}

從getPostMessage方法可以看出,傳入的Runnable被Message所持有。

public final boolean sendMessageDelayed(Message msg, long delayMillis)

{

? ? if (delayMillis < 0) {

? ? ? ? delayMillis = 0;

? ? }

? ? return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);

}

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;

? ? }

? ? return enqueueMessage(queue, msg, uptimeMillis);

}

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {

? ? msg.target = this;

? ? if (mAsynchronous) {

? ? ? ? msg.setAsynchronous(true);

? ? }

? ? return queue.enqueueMessage(msg, uptimeMillis);

}

由上面可知如下結(jié)論:

a.post方法的實(shí)現(xiàn)是與sendMessage一致的,最終都調(diào)至sendMessage中

b.干了個(gè)什么事呢:得到一個(gè)message,將它的callback設(shè)為傳入的callback(如果有的話),將它的target設(shè)為自身,然后調(diào)用MessageQueue的enqueueMessage處理該Message,實(shí)現(xiàn)原理講到MessageQueue再行討論。

1.4 dispatchMessage方法,該方法從Handler發(fā)起流程中難以看到在什么地方調(diào)用了,是一個(gè)消息處理時(shí)的回調(diào),先講一下該方法的邏輯,后面再說調(diào)用時(shí)機(jī)

public void dispatchMessage(Message msg) {

? ? if (msg.callback != null) {

? ? ? ? handleCallback(msg);

? ? } else {

? ? ? ? if (mCallback != null) {

? ? ? ? ? ? if (mCallback.handleMessage(msg)) {

? ? ? ? ? ? ? ? return;

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? handleMessage(msg);

? ? }

}

private static void handleCallback(Message message) {

? ? message.callback.run();

}

從上面的邏輯中看到如下結(jié)論:

消費(fèi)該Hanlder事件總共有三種可能的途徑,分別為Message中的callback、Handler所持有的Callback對象、Handler的自身的handleMessage方法(一般寫法是構(gòu)造匿名子類,實(shí)現(xiàn)該方法),三種途徑的優(yōu)先級從高到低。

Handler在該機(jī)制中的作用為:

a.對外提供可復(fù)用的Message

b.對外提供發(fā)消息的接口

c.對外提供回調(diào)的實(shí)現(xiàn),三種方式

2.Looper類

在主線程中使用Handler,看不到Looper,因?yàn)橄到y(tǒng)已經(jīng)幫我們自動生成了Looper,在工作線程中使用Handler則必須先調(diào)用Looper的prepare生成Looper,否則會報(bào)錯(cuò),原因如下:

測試代碼:

Thread t =? new Thread(new Runnable() {

? ? @Override

? ? public void run() {

? ? ? ? Handler handler = new Handler();

? ? }

});

t.start();

運(yùn)行后報(bào)錯(cuò):

java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()

Handler最終會調(diào)至(1.1中第一個(gè)構(gòu)造方法)

if (mLooper == null) {

? ? ? ? throw new RuntimeException(

? ? ? ? ? ? "Can't create handler inside thread that has not called Looper.prepare()");

? ? }

因此正確的寫法為:

Thread t =? new Thread(new Runnable() {

? ? @Override

? ? public void run() {

? ? ? ? Looper.prepare();

? ? ? ? Handler handler = new Handler();

? ? ? ? // ignore

? ? ? ? Looper.loop();

? ? }

});

2.1 prepare方法:

public static void prepare() {

? ? prepare(true);

}

private static void prepare(boolean quitAllowed) {

? ? if (sThreadLocal.get() != null) {

? ? ? ? throw new RuntimeException("Only one Looper may be created per thread");

? ? }

? ? sThreadLocal.set(new Looper(quitAllowed));

}

sThreadLocal變量定義如下:

static final ThreadLocal sThreadLocal = new ThreadLocal();

使用ThreadLocal類對Looper進(jìn)行了一層封裝。

像c++的內(nèi)聯(lián)函數(shù)一樣,此處我們直接內(nèi)聯(lián)一下ThreadLocal這個(gè)類,看一下該類的作用,先從Looper中跳出去一下

--------------------------------此處插入ThreadLocal類----------------------------------

3. ThreadLocal類

ThreadLocal達(dá)到的目的是:每一個(gè)ThreadLocal的變量在多個(gè)線程中都有一份copy,相互間獨(dú)立存儲,互不影響,但變量名只有一個(gè)。也就是說對于該變量的使用方來講,看起來像是只定義了一個(gè)變量,但實(shí)際上在多線程環(huán)境中,有互不影響的、每個(gè)線程都有一份的對象存在。如何作到這一點(diǎn)呢,是通過其對外提供的get方法和set方法做到的。

3.1 先來看set方法:

public void set(T value) {

? ? Thread t = Thread.currentThread();

// 第一步,拿到每個(gè)線程所對應(yīng)的ThreadLocalMap

? ? ThreadLocalMap map = getMap(t);

// 第二步,將該值存入或更新map的對應(yīng)位置

? ? if (map != null)

? ? ? ? map.set(this, value);

? ? else

? ? ? ? createMap(t, value);

}

ThreadLocalMap getMap(Thread t) {

? ? return t.threadLocals;

}

void createMap(Thread t, T firstValue) {

? ? t.threadLocals = new ThreadLocalMap(this, firstValue);

}

// ThreadLocalMap的構(gòu)造方法

ThreadLocalMap(ThreadLocal firstKey, Object firstValue) {

? ? table = new Entry[INITIAL_CAPACITY];

? ? int i = firstKey.threadLocalHashCode & (INITIAL_CAPACITY - 1);

? ? table[i] = new Entry(firstKey, firstValue);

? ? size = 1;

? ? setThreshold(INITIAL_CAPACITY);

}

// set@ThreadLocalMap

private void set(ThreadLocal key, Object value) {

? ? // We don't use a fast path as with get() because it is at

? ? // least as common to use set() to create new entries as

? ? // it is to replace existing ones, in which case, a fast

? ? // path would fail more often than not.

? ? Entry[] tab = table;

? ? int len = tab.length;

? ? int i = key.threadLocalHashCode & (len-1);

? ? for (Entry e = tab[i];

? ? ? ? e != null;

? ? ? ? e = tab[i = nextIndex(i, len)]) {

? ? ? ? ThreadLocal k = e.get();

? ? ? ? if (k == key) {

? ? ? ? ? ? e.value = value;

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? if (k == null) {

? ? ? ? ? ? replaceStaleEntry(key, value, i);

? ? ? ? ? ? return;

? ? ? ? }

? ? }

? ? tab[i] = new Entry(key, value);

? ? int sz = ++size;

? ? if (!cleanSomeSlots(i, sz) && sz >= threshold)

? ? ? ? rehash();

}

上述邏輯第一步拿到每個(gè)線程的ThreadLocalMap對象

// threadlocals#Thread

ThreadLocal.ThreadLocalMap threadLocals = null;

也就是說每個(gè)線程維護(hù)一個(gè)ThreadLocalMap來存儲該線程所用到的所有ThreadLocal變量,ThreadLocalMap的實(shí)現(xiàn)原理與HashMap基本一致,之前討論過HashMap的實(shí)現(xiàn)原理,感興趣的同學(xué)對比一下源碼就能明白。

第二步中將傳入的值存入ThreadLocalMap的對應(yīng)位置,該位置的key由ThreadLocal本身的hash值去運(yùn)算得到的。從上面的代碼中可以看出。每一個(gè)線程持有一個(gè)ThreadLocalMap,set的value將和ThreadLocal自身組成key-value結(jié)構(gòu)存在于該Map中。

3.2 get方法

public T get() {

? ? Thread t = Thread.currentThread();

? ? ThreadLocalMap map = getMap(t);

? ? if (map != null) {

? ? ? ? ThreadLocalMap.Entry e = map.getEntry(this);

? ? ? ? if (e != null) {

? ? ? ? ? ? @SuppressWarnings("unchecked")

? ? ? ? ? ? T result = (T)e.value;

? ? ? ? ? ? return result;

? ? ? ? }

? ? }

? ? return setInitialValue();

}

private T setInitialValue() {

? ? T value = initialValue();

? ? Thread t = Thread.currentThread();

? ? ThreadLocalMap map = getMap(t);

? ? if (map != null)

? ? ? ? map.set(this, value);

? ? else

? ? ? ? createMap(t, value);

? ? return value;

}

理解了set方法之后,get方法就較為簡單了,反向拿到存入的值即可,ThreadLocal對象本身在多個(gè)線程中只有一份,但通過其set和get,可以得到其包裝對象在每個(gè)線程中只有一份。

--------------------------ThreadLocal分析完畢,回至Looper----------------------------------

Looper的prepare為一個(gè)靜態(tài)方法,目的是可以生成每個(gè)線程都有一份的Looper

private static void prepare(boolean quitAllowed) {

? ? if (sThreadLocal.get() != null) {

? ? ? ? throw new RuntimeException("Only one Looper may be created per thread");

? ? }

? ? sThreadLocal.set(new Looper(quitAllowed));

}

2.2 Looper構(gòu)造方法:

private Looper(boolean quitAllowed) {

? ? mQueue = new MessageQueue(quitAllowed);

? ? mThread = Thread.currentThread();

}

持有一個(gè)MessageQueue對象,持有當(dāng)前的線程對象

2.3 loop方法

public static void loop() {

// 第一步:myLooper的實(shí)現(xiàn)看下方,得到當(dāng)前線程的Looper

? ? 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();

// 第二步:定義一個(gè)無限循環(huán)體,遍歷MessageQueue,取其中的有效Message,進(jìn)行處理,處理語名為:msg.target.dispatchMessage(msg);該方法請看上面1.4

? ? 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 slowDispatchThresholdMs = me.mSlowDispatchThresholdMs;

? ? ? ? final long traceTag = me.mTraceTag;

? ? ? ? if (traceTag != 0 && Trace.isTagEnabled(traceTag)) {

? ? ? ? ? ? Trace.traceBegin(traceTag, msg.target.getTraceName(msg));

? ? ? ? }

? ? ? ? final long start = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();

? ? ? ? final long end;

? ? ? ? try {

? ? ? ? ? ? msg.target.dispatchMessage(msg);

? ? ? ? ? ? end = (slowDispatchThresholdMs == 0) ? 0 : SystemClock.uptimeMillis();

? ? ? ? } finally {

? ? ? ? ? ? if (traceTag != 0) {

? ? ? ? ? ? ? ? Trace.traceEnd(traceTag);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? if (slowDispatchThresholdMs > 0) {

? ? ? ? ? ? final long time = end - start;

? ? ? ? ? ? if (time > slowDispatchThresholdMs) {

? ? ? ? ? ? ? ? Slog.w(TAG, "Dispatch took " + time + "ms on "

? ? ? ? ? ? ? ? ? ? ? ? + Thread.currentThread().getName() + ", h=" +

? ? ? ? ? ? ? ? ? ? ? ? msg.target + " cb=" + msg.callback + " msg=" + msg.what);

? ? ? ? ? ? }

? ? ? ? }

? ? ? ? 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);

? ? ? ? }

// 此處實(shí)現(xiàn)Message的循環(huán)利用

? ? ? ? msg.recycleUnchecked();

? ? }

}

public static @Nullable Looper myLooper() {

? ? return sThreadLocal.get();

}

在loop的處理中,有一點(diǎn)需重點(diǎn)關(guān)注,loop在線程中是一個(gè)無限循環(huán),跳出該循環(huán)的條件為MessageQueue的next返回值為空,看一下4.2的next方法實(shí)現(xiàn),返回空依賴于mQuitting變量,也就是說在線程中不需要一直等待事件時(shí),要把MessageQueue該變量置為true,設(shè)置入口為quit@Looper

2.4 quit方法

public void quit() {

? ? mQueue.quit(false);

}

//quit@MessageQueue

void quit(boolean safe) {

? ? if (!mQuitAllowed) {

? ? ? ? throw new IllegalStateException("Main thread not allowed to quit.");

? ? }

? ? synchronized (this) {

? ? ? ? if (mQuitting) {

? ? ? ? ? ? return;

? ? ? ? }

? ? ? ? mQuitting = true;

? ? ? ? if (safe) {

? ? ? ? ? ? removeAllFutureMessagesLocked();

? ? ? ? } else {

? ? ? ? ? ? removeAllMessagesLocked();

? ? ? ? }

? ? ? ? // We can assume mPtr != 0 because mQuitting was previously false.

? ? ? ? nativeWake(mPtr);

? ? }

}

總結(jié)一下:Looper在Handler機(jī)制中起的作用是:

a.提供每個(gè)線程唯一的實(shí)例

b.觸發(fā)MessageQueue的循環(huán)遍歷

4. MessageQueue類

顧名思義,該類需提供三個(gè)能力:

a.Message隊(duì)列存儲

b.Message入隊(duì)

c.Message出隊(duì)

Message隊(duì)列以鏈表形式存儲,其頭部指針存放于mMessages

4.1 enqueueMessage方法,該方法用于Message入隊(duì)

boolean enqueueMessage(Message msg, long when) {

? ? if (msg.target == null) {

? ? ? ? throw new IllegalArgumentException("Message must have a target.");

? ? }

? ? 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;

? ? ? ? }

? ? ? ? msg.markInUse();

? ? ? ? msg.when = when;

? ? ? ? Message p = mMessages;

? ? ? ? boolean needWake;

// 以下為入隊(duì)的關(guān)鍵代碼,找到鏈表的隊(duì)尾,放入該Message

? ? ? ? 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;

// 注意,入隊(duì)的時(shí)候,已經(jīng)按時(shí)間次序?qū)essage插入隊(duì)列中的合適位置

? ? ? ? ? ? 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;

? ? ? ? }

? ? ? ? // We can assume mPtr != 0 because mQuitting is false.

? ? ? ? if (needWake) {

? ? ? ? ? ? nativeWake(mPtr);

? ? ? ? }

? ? }

? ? return true;

}

需要注意,在上面的入隊(duì)處理中,要按Handler傳入的執(zhí)行時(shí)間插入

enqueueMessage調(diào)用的入口請查看1.3

4.2 next方法,該方法用于MessageQueue出隊(duì)

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;

? ? if (ptr == 0) {

? ? ? ? return null;

? ? }

? ? int pendingIdleHandlerCount = -1; // -1 only during first iteration

? ? int nextPollTimeoutMillis = 0;

? ? for (;;) {

? ? ? ? if (nextPollTimeoutMillis != 0) {

? ? ? ? ? ? Binder.flushPendingCommands();

? ? ? ? }

? ? ? ? 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;

// 第二步:取到最早入隊(duì)的有效的Message

? ? ? ? ? ? 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();

? ? ? ? ? ? ? ? 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;

? ? }

}

next方法的調(diào)用入口位于2.3中

小結(jié)一下,通過上面的代碼講解,可以得到以下幾個(gè)結(jié)論:

1. 首先Handler對象本身位于構(gòu)造Handler的當(dāng)前線程,他的事件要發(fā)往那個(gè)線程,取決于構(gòu)造方法傳 的Looper變量

2. MessageQueue與Looper位于Handler所要發(fā)往的工作線程中,Looper持有MessageQueue對象,MessageQueue中看不到Looper

3. Looper與線程為1對1的關(guān)系,也就是說一個(gè)線程只有一個(gè)Looper,一個(gè)Looper只服務(wù)于一個(gè)線程,達(dá)到這個(gè)目的是通過ThreadLocal包裝Looper實(shí)現(xiàn)的

4. 從線程的角度講,Handler對象自身與線程沒有任何關(guān)系,它是通過Looper持有的MessageQueue實(shí)現(xiàn)向Looper所服務(wù)的線程事件隊(duì)列(MessageQueue)插入事件(Message)的

看一下文章開頭所說的幾個(gè)問題是不是已經(jīng)有了答案:

a.Handler是如何實(shí)現(xiàn)多個(gè)線程之前事件傳遞的?

請看上面總結(jié)的第4點(diǎn)

b.Handler、Message、MessageQueue、Looper相互之間的數(shù)量比是多少,都是1:1嗎?

Handler n--1 Looper(以主線程為例,主線程的Looper可以定義非常多Handler)

Looper持有一個(gè)MessageQueue(不可逆,看上面總結(jié)的第2點(diǎn))

MessageQueue 1--n Message

c.每個(gè)變量運(yùn)行的線程是那個(gè)?

Handler位于定義線程、Looper、MessageQueue位于工作線程,線程的輪詢依賴于Looper.loop

d.ThreadLocal是怎么回事,在Handler機(jī)制中起什么作用?

可查看代碼分析部分的第3部分

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容