博客原文地址:http://jockio.github.io/2016/08/16/source-code-of-handler-and-looper/
前言
首先我們要知道,創(chuàng)建Handler之前,要先創(chuàng)建與之配套的Looper。
在主線程中,系統(tǒng)已經初始化了一個 Looper 對象,因此程序直接創(chuàng)建 Handler 對象即可,然后就可以通過 Handler 來發(fā)送、處理消息了。
在子線程中,必須自己創(chuàng)建一個 Looper 對象,并啟動它。
創(chuàng)建 Looper 對象調用它的 prepare 方法即可(prepare 方法保證每個線程最多只有一個 Looper 對象),然后調用 Looper 的靜態(tài) loop 方法來啟動它。loop 方法使用一個死循環(huán)不斷地從MessageQueue 中取消息,并將取出的消息分發(fā)給該消息對應的 Handler 處理。至于它們具體做了哪些事,我們會在后面詳細講述。
Looper的創(chuàng)建
我們先看一下Looper的構造函數(shù)
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
首先我們注意到該構造方法是被private修飾的,也就是說我們無法通過new的方式來創(chuàng)建Looper。其次,我們可以從Looper的構造方法中看出,在創(chuàng)建Looper的時候,創(chuàng)建了與之配套的MessageQueue,然后獲取了創(chuàng)建當前Looper線程的引用。
而要想創(chuàng)建Looper,只需調用Looper.prepare();。該方法保證了一個線程只能創(chuàng)建一個與之相關聯(lián)的Looper,并且將創(chuàng)建出的Looper與當前線程綁定起來。
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));
}
Handler的創(chuàng)建
Looper對象成功創(chuàng)建之后,我們再來看看Handler。當我們調用Handler的無參構造函數(shù)創(chuàng)建Handler時,它內部調用了另一個重載的構造方法this(null, false)。
public Handler(Callback callback, boolean async) {
...//something we just ignore
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;
}
從構造方法中,我們可以看出,handler獲取了與當前線程相關聯(lián)的Looper及MessageQueue的引用。
Handler 發(fā)送消息
創(chuàng)建完Handler之后,我們先從handler.sendMessage()說起:
public class MainActivity extends Activity{
protected void onCreate(Bundle onSavedInstanceState){
super.onCreate(onSavedInstanceState);
setContentView(R.layout.main);
MyRunnable mRunnable = new MyRunnable();
Thread mThread = new Thread(mRunnable);
mThread.start();
}
public static Handler = new Handler(){
@Override
public void handleMessage(Message msg){
//do some magic
}
};
static class MyRunnable implements Runnable{
@Override
public void run(){
Message msg = Message.obtain();
//do some magic
handler.sendMessage(msg);
}
}
}
而不管我們調用sendEmptyMessage()或者是sendMessage(),最終都會走到這里:
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);
}
關鍵是最后return時,調用了enqueueMessage(),我們一起看一下該方法的具體實現(xiàn):
private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
從enqueueMessage的方法實現(xiàn)可以看出,要發(fā)送的消息獲取到了當前Handler的引用,也就是msg.target 。然后這條信息被加入到了與當前線程相關聯(lián)的MessageQueue中。到此,發(fā)送消息的邏輯已經結束。
那么Handler處理消息的方法又是在什么時候回調的呢?要弄明白這一點,我們要對Looper.loop()進行分析。
Looper.loop();
前面我們也已經提過,要創(chuàng)建一個Handler其實是需要三個步驟的:
- 調用
Looper.prepare(); - 創(chuàng)建Handler
- 調用
Looper.loop();
?
前面兩步我們已經講解過了,那你肯定會好奇,loop()中到底做了什么呢?我們一起來看一下。
public static void loop() {
//獲取與當前線程相關聯(lián)的Looper對象
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//獲取與Looper對象相匹配的MessageQueue
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();
for (;;) {
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...//something we just ignore
msg.target.dispatchMessage(msg);
...//something we just ignore
// Mark the message as in use while it remains in the recycled object pool. Clear out all other details.
msg.recycleUnchecked();
}
}
從源碼可以看出,loop()其實調用了一個死循環(huán),不斷的從與Looper配套的MessageQueue中取消息,然后調用msg.target.dispatchMessage(msg);進行消息的分發(fā)。
前面Handler發(fā)送消息的時候,我們已經分析過,每個要發(fā)送的Message都獲取到了發(fā)送它的Handler的引用,也就是msg.target。因此這里msg.target.dispatchMessage(msg);其實也就是調用了handler的dispatchMessage進行消息的分發(fā)。
Handler的handleMessage()何時被回調?
我們一起來看一下handler的dispatchMessage():
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
很明顯,就是在這里,Handler的handleMessage被回調了。
綜上,我們可以說,是在Looper.loop()中,當循環(huán)不斷的從MessageQueue中獲取消息時,間接調用了Handler的handleMessage()方法。