/**
Handler、Looper、Message三者之間的關係,無外乎就是開始Looper會開始無限的循環,目的是在消息隊列中進行獲取Message,有則取無在等;而Handler則是在發送Message和handlerMessage方面起作用,發送的Message則是發送到消息隊列中,handlerMessage則是處理Looper發過來的消息
*/
先附一張三者關係圖方便理解
源碼分析
首先我們來看一下Handler的構造方法
/**
* Default constructor associates this handler with the queue for the
* current thread.
*
* If there isn't one, this handler won't be able to receive messages.
*/
public Handler() {
...
//獲取Looper對象
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 = null;
}
這裏有一個判斷,這裏的判斷主要的針對子線程new Handler的情況,因爲在主線程Looper會自動創建在子線程裏則沒有。
爲了驗證我們來看主線程的方法ActivityThread類main方法
public static final void main(String[] args) {
...
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
...
}
}
Looper.prepareMainLooper()
public static final void prepare() {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper());
}
public static final void prepareMainLooper() {
prepare();
setMainLooper(myLooper());
if (Process.supportsProcesses()) {
myLooper().mQueue.mQuitAllowed = false;
}
}
從代碼中可以看出其實main方法就是調用了prepare方法,而這個方法是將new Looper()放入ThreadLocal裏面,所謂ThreadLocal類也HashMap是一樣的,只不過它裏面默認是將Key存儲的每個線程,用途:保證每個線程所擁有的value是唯一的。ok,我們接下來看Handler的構造方法
Looper.myLooper()方法
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static final Looper myLooper() {
return (Looper)sThreadLocal.get();
}
這裏只是將ThreadLocal類裏面存入的Looper取出來,然後我們看ActivityThread類裏面
Loop.loop()方法
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static final void loop() {
Looper me = myLooper();
MessageQueue queue = me.mQueue;
...
while (true) {
Message msg = queue.next(); // might block
//if (!me.mRun) {
// break;
//}
if (msg != null) {
if (msg.target == null) {
// No target is a magic identifier for the quit message.
return;
}
msg.target.dispatchMessage(msg);
...
}
}
}
調用這個方法就進入了無限循環中,Looper將從MessageQueue中不斷的取消息(有的時候則取沒有的時候等待),當取到數據的時候會調用msg.target.dispatchMessage(msg)方法將Message回傳到Handler中。target是什麼呢?其實你順着源碼查看你會發現target其實是Handler對象,更準確的是該Message所屬Handler對象。
msg.target.dispatchMessage(msg)方法
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
這裏的msg.callback和mCallback在Message和Handler創建的時候有相應的參數,這裏最後的情況纔是去執行handler的handlerMessage方法,這裏需要注意嘍,如果你在Message和Handler裏面使用Callback就不會在調用handlerMessage。
對於Looper取消息和發送消息就是這些,接下來來看一下Handler的發送消息到消息隊列的過程
最終調用的sendMessageAtTime()方法
public boolean sendMessageAtTime(Message msg, long uptimeMillis)
{
boolean sent = false;
MessageQueue queue = mQueue;
if (queue != null) {
msg.target = this;
sent = queue.enqueueMessage(msg, uptimeMillis);
}
else {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
}
return sent;
}
每次的發送中將當前發送的Handler對象賦值給target ,整好對應上面Looper取出Message之後根據target分發給相應的Handler的過程。
MessageQueue.enqueueMessage()方法
final boolean enqueueMessage(Message msg, long when) {
...
msg.when = when;
//Log.d("MessageQueue", "Enqueing: " + msg);
Message p = mMessages;
if (p == null || when == 0 || when < p.when) {
msg.next = p;
mMessages = msg;
needWake = mBlocked; // new head, might need to wake up
} else {
Message prev = null;
while (p != null && p.when <= when) {
prev = p;
p = p.next;
}
msg.next = prev.next;
prev.next = msg;
needWake = false; // still waiting on head, no need to wake up
}
}
if (needWake) {
nativeWake(mPtr);
}
return true;
}
在第一個if語句中通過比較傳入的when和隊列中第一個Message的when的大小,如果傳入的小則需要馬上進行處理,將needWake喚醒的狀態置爲true
否則的話將對消息隊列進行遍歷將傳入的Message根據when插入到裏面,並且將喚醒狀態置爲false。
到這裏三者關係就大致講完了,如果想了解更多請看鴻洋大神的: Android 異步消息處理機制 讓你深入理解 Looper、Handler、Message三者關係