原理
個人的一點理解
??本質上,Handler的使用就是從一個MessageQueue中不斷取出其所綁定的Message,隨后調用其本身的handleMessage(...)
方法郭计,但是使用Handler有三個基本要點:
??1.每個線程線程只有一個Looper指么,而Looper其實就是引用了一個MessageQueue
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)); //使得Looper和當前線程相關綁定起來
}
??2.Looper.loop()
包含了一個死循環(huán)for(;;)
宴合,在該循環(huán)中不斷對當前線程唯一的Looper所引用的MessageQueeue執(zhí)行出椙。或者出隊列操作,并通過message.target
驅使每一條信息所綁定的Handler對該條message進行處理物舒。
public static void loop() {
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;
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
msg.target.dispatchMessage(msg); //無論是調用post()還是setTarget()色洞,最后都會調用這個
msg.recycleUnchecked();
}
}
??3.使用Handler.setTarget()
或者Handler.post(...)
在本質上就是往本線程對應的Looper傳入一個message,也就是進椆诳瑁或進隊列操作火诸,但兩種方法有一個細微區(qū)別,setTarget()
的結果是使得message.callback = null
荠察,而post(Runnable r)
則是使得message.callback = r
置蜀。這個細微區(qū)別就導致了是該條message的處理時機。實際上參照第2點代碼可以知道悉盆,方法loop()
中每次出椂⒒纾或出隊列都會調用msg.target.dispatchMessage(msg);
,那么接下來閱讀以下代碼:
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
??明顯可以看到方法內會根據(jù)message.callback
是否為空選擇不同的操作來執(zhí)行,也就是說焕盟,如果Handler調用的不是setTarget()
秋秤,而是post()
的話,是不會執(zhí)行Handler的handleMessage(msg)
的脚翘,而是直接調用post(Runnable r)
中的參數(shù)
??還有相當重要的一點是灼卢,主線程會自動調用Looper.prepareMainLooper();
來完成Looper的初始化,而我們手動創(chuàng)建的線程是需要自己去手動調用Looper.prepare()
完成初始化才可以獲得一個指向MessageQueue的Looper来农。
??看完終于明白了Handler的運行機制的一點理解鞋真,隨手寫下來加強記憶,如果有錯誤沃于,請指正灿巧。