Android Handler機(jī)制系列文章整體內(nèi)容如下:
- Android Handler機(jī)制1之Thread
- Android Handler機(jī)制2之ThreadLocal
- Android Handler機(jī)制3之SystemClock類
- Android Handler機(jī)制4之Looper與Handler簡介
- Android Handler機(jī)制5之Message簡介與消息對象對象池
- Android Handler機(jī)制6之MessageQueue簡介
- Android Handler機(jī)制7之消息發(fā)送
- Android Handler機(jī)制8之消息的取出與消息的其他操作
- Android Handler機(jī)制9之Handler的Native實(shí)現(xiàn)前奏之Linux IO多路復(fù)用
- Android Handler機(jī)制10之Handdler的Native實(shí)現(xiàn)Native的實(shí)現(xiàn)
- Android Handler機(jī)制11之Handler機(jī)制總結(jié)
- Android Handler機(jī)制12之Callable、Future和FutureTask
- Android Handler機(jī)制13之AsyncTask源碼解析
本片文章的主要內(nèi)容如下:
- 1 概述
- 2 相應(yīng)類的理解
- 3 Handle原理詳解
- 4 主線程的Looper的初始化
一、 概述
工欲善其事必先利其器,在Android的源碼世界里面,有兩大利器,一是Binder IPC機(jī)制,關(guān)于Binder的內(nèi)容上面已經(jīng)講過了。另一個(gè)便是Handler消息機(jī)制(由Handler/Looper/MessageQueue等構(gòu)成)。Android有大量的消息驅(qū)動(dòng)方法來進(jìn)行交互,就像Android的四大組件(Activity、Service、Broadcast、ContentProvider)的啟動(dòng)過程交互,都離不開Handler的消息機(jī)制,所以Android系統(tǒng)某種意義上說也是一種以消息驅(qū)動(dòng)的系統(tǒng)。
那Android為什么要采用Handler的消息機(jī)制那?
答: 在Android中,只有主線程才能更新UI,但是主線程不能進(jìn)行耗時(shí)操作,否則會(huì)產(chǎn)生ANR異常,所以常常把耗時(shí)操作放到其他子線程進(jìn)程。如果在子線程中需要更新UI,一般都是通過Handler發(fā)送消息,主線接受消息并進(jìn)行相應(yīng)的邏輯處理。當(dāng)然除了直接使用Handler,還可以用View的post()方法、Activity的runOnUIThread()方法來更新UI和AsyncTask其實(shí)他們本質(zhì)也是使用了Handler來實(shí)現(xiàn)的。后面我們會(huì)單獨(dú)說他們
要理解Handler的消息機(jī)制,就不得不說Handler/Looper/Message/MessageQueue/Message這四4個(gè)類,下面我們先大概了解下這幾個(gè)類
二、 相應(yīng)類的理解
關(guān)于類的理解,還是以官網(wǎng)上的類介紹為主
(一) Handler
1、什么是Handler
A Handler allows you to send and process Message
and Runnable objects associated with a thread's MessageQueue
. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
簡單翻一下:
Handler是一個(gè)可以通過關(guān)聯(lián)一個(gè)消息隊(duì)列來發(fā)送和處理消息,發(fā)送或處理Runnable對象的一個(gè)處理程序,每個(gè)Handler都關(guān)聯(lián)一個(gè)單個(gè)的線程和消息隊(duì)列,當(dāng)你創(chuàng)建一個(gè)新的Handler的時(shí)候它就將綁定到一個(gè)線程或線程上的消息隊(duì)列,從那時(shí)起,這個(gè)Handler就將為這個(gè)消息隊(duì)列提供消息或Runnable對象,處理消息隊(duì)列釋放出來的消息或Runnable對象。
2、Handler有什么用
There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
簡單翻譯 一下:
Handler有兩個(gè)主要的用途
- 1 安排消息和Runnable對象在未來之星
- 2 將你的一個(gè)動(dòng)作放在不同的線程上執(zhí)行
3、怎么使用Handler
Scheduling messages is accomplished with the post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long) methods. The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received; the sendMessage versions allow you to enqueue a Message object containing a bundle of data that will be processed by the Handler's handleMessage(Message) method (requiring that you implement a subclass of Handler).
翻譯一下:
通過重寫post(Runnable)、postAtTime(Runnable, long)、postDelayed(Runnable, long)、sendEmptyMessage(int)、sendMessage(Message)、sendMessageAtTime(Message, long)、sendMessageDelayed(Message, long)來完成發(fā)送消息。當(dāng)前版本允許你通過消息隊(duì)列接受一個(gè)Runnable對象,sendMessage方法當(dāng)前版本允許你將一個(gè)包的數(shù)據(jù)通過消息隊(duì)列的方式處理,但是你需要重寫Handler的handleMessage方法
When posting or sending to a Handler, you can either allow the item to be processed as soon as the message queue is ready to do so, or specify a delay before it gets processed or absolute time for it to be processed. The latter two allow you to implement timeouts, ticks, and other timing-based behavior.
翻譯一下:
當(dāng)你發(fā)送一個(gè)Handler時(shí),你可以使消息隊(duì)列(MessageQueue)盡快去處理已經(jīng)準(zhǔn)備好的條目,或者指定一個(gè)延遲處理的時(shí)間或者指定時(shí)間處理,后兩者允許你實(shí)現(xiàn)超時(shí),Ticks(系統(tǒng)相對的時(shí)間單位)和其他時(shí)間段為基礎(chǔ)的行為。
When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. The given Runnable or Message will then be scheduled in the Handler's message queue and processed when appropriate.
即當(dāng)一個(gè)進(jìn)程被應(yīng)用程序創(chuàng)建時(shí),它的主線程會(huì)運(yùn)行一個(gè)消息隊(duì)列負(fù)責(zé)管理它創(chuàng)建的高層應(yīng)用程序?qū)ο?如Activity、Broadcast Receiver等)和任何它的窗口創(chuàng)建的對象,你可以通過一個(gè)Handler,創(chuàng)建自己的線程來實(shí)現(xiàn)與主線程之間的交互,但前提是你得在你的線程重寫sendMessage方法并寫上一行行代碼,這樣你給定的Runnable或者M(jìn)essage將被MessageQueue(消息隊(duì)列)預(yù)定,并在合適的時(shí)間處理
注意:有心的同學(xué)會(huì)注意,我們在進(jìn)行Handler源碼分析的時(shí)候,可以知道Handler中的Message是分2中類型的,一種是Message,就是Message對象,一種是CallMessage,就是Runnable對象,但是MessageQueue中只支持DataMessage,再插入到MessageQueue的時(shí)候,會(huì)把Runnable對象封裝到Message對象中。
(二) Looper
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
翻譯一下:
用于為線程運(yùn)行消息循環(huán)的類。默認(rèn)線程沒有與它們相關(guān)聯(lián)的消息喜歡;所以要在運(yùn)行循環(huán)的線程中調(diào)用prepare(),然后調(diào)用loop()讓它循環(huán)處理消息,直到循環(huán)停止。
與消息循環(huán)的交互是通過Handler類
下面這個(gè)是一個(gè)典型的Looper線程實(shí)例,它使用prepar()和loop()的分割來創(chuàng)建一個(gè)初始的Handler與Looper進(jìn)行通信。
三、 Handle原理詳解
(一)、模型
Handler的消息機(jī)制主要包含:
- Message:消息
- MessageQueue:消息隊(duì)列的
- Handler:消息管理類向消息池發(fā)送各種消息事件
- Looper:不斷的循環(huán)執(zhí)行(Looper.loop),按分發(fā)機(jī)制將消息分發(fā)給目標(biāo)處理者
(二)、架構(gòu)圖

(三)、舉例說明
我們先用一個(gè)典型的關(guān)于Handler/Looper的線程為例展示
代碼如下:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
//情景1
Looper.prepare();
//情景3
mHandler = new Handler() {
public void handleMessage(Message msg) {
//TODO 定義消息處理邏輯.
//情景4
Message msg=Message.obtain();
}
};
// 情景2
Looper.loop();
}
}
OK,那我們便依照上面的的四個(gè)情景依次展開
1、情景1 Looper.prepare();
代碼在Looper.java的82行
/** Initialize the current thread as a looper.
* This gives you a chance to create handlers that then reference
* this looper, before actually starting the loop. Be sure to call
* {@link #loop()} after calling this method, and end it by calling
* {@link #quit()}.
*/
public static void prepare() {
prepare(true);
}
看下prepare()方法的注釋,翻譯一下:
初始化當(dāng)前線程和Looper,這樣可以在實(shí)際開始啟動(dòng)循環(huán)(loop())之前創(chuàng)建一個(gè)Handler并且關(guān)聯(lián)一個(gè)looper。確保在先調(diào)用這個(gè)方法,然后調(diào)用loop()方法,并且通過調(diào)用quit()結(jié)束。
我們發(fā)現(xiàn)prepare()方法里面什么都沒有調(diào)用,就是調(diào)用了prepare(true),那我們繼續(xù)跟蹤下
1.1、 prepare(boolean)方法
這里面的入?yún)oolean表示Looper是否允許退出,true就表示允許退出,對于false則表示Looper不允許退出。
代碼在Looper.java的86行
private static void prepare(boolean quitAllowed) {
//每個(gè)線程只允許執(zhí)行一次該方法,第二次執(zhí)行的線程的TLS已有數(shù)據(jù),則會(huì)拋出異常。
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
//創(chuàng)建Looper對象,并且保存到當(dāng)前線程的TLS區(qū)域。
sThreadLocal.set(new Looper(quitAllowed));
}
那sThreadLocal是什么?我們來看下
代碼在Looper.java的86行
// sThreadLocal.get() will return null unless you've called prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
原來是ThreadLocal啊,關(guān)于ThreadLocal的內(nèi)容請參考Android Handler機(jī)制2之ThreadLocal
我們看到上面調(diào)用了new Looper(quitAllowed),那我們就來看下這個(gè)Looper的構(gòu)造函
1.2、 Looper(boolean)構(gòu)造函數(shù)
private Looper(boolean quitAllowed) {
// 創(chuàng)建MessageQueue對象
mQueue = new MessageQueue(quitAllowed);
// 記錄當(dāng)前線程
mThread = Thread.currentThread();
}
通過上面代碼,我們發(fā)現(xiàn)就是創(chuàng)建了一個(gè)MessageQueue,并且把當(dāng)前線程賦值給本地變量的mThread。
- 1 這樣就實(shí)現(xiàn)了Looper和MessageQueue的關(guān)聯(lián)
- 2 這樣就實(shí)現(xiàn)了Thread和Looper的關(guān)聯(lián)
1.3、 Looper類的思考
因?yàn)槭菢?gòu)造函數(shù),我們看下Looper這個(gè)類的結(jié)構(gòu),如下圖

咦,大家發(fā)現(xiàn)沒,Loop類就一個(gè)構(gòu)造函數(shù),也就是我們上面的說的Looper(boolean) 這個(gè)構(gòu)造函數(shù)。而且這個(gè)構(gòu)造函數(shù)也是private。我們又發(fā)現(xiàn)在這個(gè)私有的Looper(boolean)的構(gòu)造函數(shù),只有在private static void prepare(boolean quitAllowed)調(diào)用,而這個(gè)靜態(tài)方法也是private的,我們看下這個(gè)方法在哪里被調(diào)用

所以我們得出結(jié)論
私有的構(gòu)造函數(shù) => 私有的靜態(tài)方法prepare(boolean) => static prepare()/prepareMainLooper()
所以我們知道,Looper這個(gè)類的對象不能直接創(chuàng)建,必須通過Looper來的兩個(gè)靜態(tài)方法prepare()/prepareMainLooper()來間接創(chuàng)建
1.4、prepareMainLooper()方法
代碼在Looper.java的99行
/**
* Initialize the current thread as a looper, marking it as an
* application's main looper. The main looper for your application
* is created by the Android environment, so you should never need
* to call this function yourself. See also: {@link #prepare()}
*/
public static void prepareMainLooper() {
// 設(shè)置不允許退出的Looper
prepare(false);
synchronized (Looper.class) {
//將當(dāng)前的Looper保存為Looper。每個(gè)線程只允許執(zhí)行一次
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
① 注釋
首先翻譯一下注釋
初始化當(dāng)前當(dāng)前線程的looper。并且標(biāo)記為一個(gè)程序的主Looper。由Android環(huán)境來創(chuàng)建應(yīng)用程序的主Looper。因此這個(gè)方法不能由咱們來調(diào)用。另請參閱prepare()
② 方法解析
- 首先 通過方法我們看到調(diào)用了prepare(false);注意這里的入?yún)⑹莊alse
- 其次 做了sMainLooper的非空判斷,如果是有值的,直接拋異常,因?yàn)檫@個(gè)sMainLooper必須是空,因?yàn)橹骶€程有且只能調(diào)用一次prepareMainLooper(),如果sMainLooper有值,怎說說明prepareMainLooper()已經(jīng)被調(diào)用了,而sMainLooper的賦值是由myLooper來執(zhí)行,
- 最后調(diào)用myLooper()方法來給sMainLooper進(jìn)行賦值。
③ sMainLooper
上面提到了一個(gè)變量時(shí)sMainLooper,那sMainLooper到底是什么?我們來看下源代碼.
代碼在Looper.java的 69行
private static Looper sMainLooper; // guarded by Looper.class
通道源碼我們知道原來就是Looper對象啊。但是它是靜態(tài)的。而在Java7之前,靜態(tài)變量存在永久代(PermGen)。在Hospot JVM上,PermGen 就是方法區(qū);在Java7之后,將變量的存儲(chǔ)轉(zhuǎn)移到了堆。所以說這個(gè)sMainLooper就是主線程的Looper。所以只有通過prepareMainLooper()就可以給主線程Looper賦值了。
1.5、myLooper()方法
代碼在Looper.java的173行
/**
* Return the Looper object associated with the current thread. Returns
* null if the calling thread is not associated with a Looper.
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
這里的sThreadLocal.get()是和prepare(boolean)方法里面的sThreadLocal.set(new Looper(quitAllowed));一一對應(yīng)的。而在prepareMainLooper()方法里面,
提出一個(gè)問題,在prepareMainLooper里面調(diào)用myLooper(),那么myLooper()方法的返回有沒有可能為null?
答:第一步就是調(diào)用prepare(false);,所以說myLooper()這個(gè)方法的返回值是一定有值的。
2、情景2 Looper.loop();
代碼在Looper.java的 122行
/**
* Run the message queue in this thread. Be sure to call
* {@link #quit()} to end the loop.
*/
public static void loop() {
// 獲取TLS存儲(chǔ)的Looper對象
final Looper me = myLooper();
//沒有Looper 對象,直接拋異常
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//獲取當(dāng)前Looper對應(yīng)的消息隊(duì)列
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();
// 確保權(quán)限檢查基于本地進(jìn)程,而不是基于最初調(diào)用進(jìn)程
final long ident = Binder.clearCallingIdentity();
// 進(jìn)入 loop的主循環(huán)方法
// 一個(gè)死循環(huán),不停的處理消息隊(duì)列中的消息,消息的獲取是通過MessageQueue的next()方法實(shí)現(xiàn)
for (;;) {
// 可能會(huì)阻塞
Message msg = queue.next(); // might block
// 如果沒有消息,則退出循環(huán)
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
// 默認(rèn)為null,可通過setMessageLogging()方法來指定輸出,用于debug功能
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
// 用于分發(fā)消息,調(diào)用Message的target變量(也就是Handler了)的dispatchMessage方法來處理消息
msg.target.dispatchMessage(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.
// 確保分發(fā)過程中identity不會(huì)損壞
final long newIdent = Binder.clearCallingIdentity();
if (ident != newIdent) {
// 打印identiy改變的log,在分發(fā)消息過程中是不希望身份被改變
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);
}
// 將Message放入消息池
msg.recycleUnchecked();
}
}
loop進(jìn)入循環(huán)模式,不斷重復(fù)下面的操作,直到?jīng)]有消息時(shí)退出循環(huán)
- 讀取MessageQueue的下一條Message
- 把Message分發(fā)給相應(yīng)的target
- 再把分發(fā)后的Message回到消息池,以便重復(fù)利用
這里有幾個(gè)重要方法,我們分別會(huì)在后面的文章中說明
- MessageQueue.next()方法: 讀取下一條Message,有阻塞
- 會(huì)在Android Handler機(jī)制6之MessageQueue簡介中講解MessageQueue.next()方法
- Message.Handler.dispatchMessage(Message msg)方法:消息分發(fā)
- 會(huì)在Android Handler機(jī)制7之消息傳遞流程中講解 Message.Handler.dispatchMessage(Message msg)方法
- Message.recycleUnchecked()方法:消息放入消息池
- 會(huì)在Android Handler機(jī)制5之Message簡介與消息對象對象池中講解Message.recycleUnchecked()方法
3 Looper的退出循環(huán)方法
上面了開啟循環(huán)的方法,那么怎么退出循環(huán)?Looper里面退出循環(huán)有兩個(gè)方法分別是quit()和quitSafely()方法
3.1、Looper.quit()方法
代碼在Looper.java的 227行
/**
* Quits the looper.
* <p>
* Causes the {@link #loop} method to terminate without processing any
* more messages in the message queue.
* </p><p>
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
* </p><p class="note">
* Using this method may be unsafe because some messages may not be delivered
* before the looper terminates. Consider using {@link #quitSafely} instead to ensure
* that all pending work is completed in an orderly manner.
* </p>
*
* @see #quitSafely
*/
public void quit() {
mQueue.quit(false);
}
① 注釋
簡單的翻譯一下:
- 退出循環(huán)
- 將終止(loop()方法)而不處理消息隊(duì)列中的任何更多消息。在調(diào)用quit()后,任何嘗試去發(fā)送消息都是失敗的。例如Handler.sendMessage(Message)方法將返回false。因?yàn)檠h(huán)終止之后一些message可能會(huì)被無法傳遞,所以這個(gè)方法是不安全的??梢钥紤]使用quitSafely()方法來確保所有的工作有序地完成。
② 方法內(nèi)容:
Looper的quit()方法內(nèi)部的本質(zhì)是調(diào)用mQueue的quit()的方法,入?yún)⑹莊alse
3.2、Looper.quitSafely()方法
代碼在Looper.java的 227行
/**
* Quits the looper safely.
* <p>
* Causes the {@link #loop} method to terminate as soon as all remaining messages
* in the message queue that are already due to be delivered have been handled.
* However pending delayed messages with due times in the future will not be
* delivered before the loop terminates.
* </p><p>
* Any attempt to post messages to the queue after the looper is asked to quit will fail.
* For example, the {@link Handler#sendMessage(Message)} method will return false.
* </p>
*/
public void quitSafely() {
mQueue.quit(true);
}
① 注釋
簡單的翻譯一下:
- 安全退出循環(huán)
- 調(diào)用quitSafely()方法會(huì)使循環(huán)結(jié)束,只要消息隊(duì)列中已經(jīng)被傳遞的所有消息都將被處理。然而,在循環(huán)結(jié)束之前,將來不會(huì)提交處理延遲消息。
- 調(diào)用退出后,所有嘗試去發(fā)送消息都將失敗。就像調(diào)用Handler.sendMessage(Message)將返回false。
② 方法內(nèi)容:
Looper的quit()方法內(nèi)部的本質(zhì)是調(diào)用mQueue的quit()的方法,入?yún)⑹莟rue
3.3、MessageQueue.quit(boolean)方法
代碼在MessageQueue.java的 413行
void quit(boolean safe) {
//當(dāng)mQuitAllowed為false,表示不運(yùn)行退出,強(qiáng)行調(diào)用quit()會(huì)超出異常
//mQuitAllowed 是在Looper構(gòu)造函數(shù)里面構(gòu)造MessageQueue()以參數(shù)參進(jìn)去的
if (!mQuitAllowed) {
throw new IllegalStateException("Main thread not allowed to quit.");
}
synchronized (this) {
// 防止多次執(zhí)行退出操作
if (mQuitting) {
return;
}
mQuitting = true;
if (safe) {
//移除尚未觸發(fā)的所有消息
removeAllFutureMessagesLocked();
} else {
//移除所有消息
removeAllMessagesLocked();
}
// We can assume mPtr != 0 because mQuitting was previously false.
//mQuitting=false,那么認(rèn)定mPtr!=0
nativeWake(mPtr);
}
}
消息退出的方式:
- 當(dāng)safe=true,只移除尚未觸發(fā)的所有消息,對于正在觸發(fā)的消息并不移除
- 當(dāng)safe=false,移除所有消息
4、情景3:創(chuàng)建Handler對象
看到Handler對象,首先要看下Handler的構(gòu)造函數(shù)

好多的構(gòu)造函數(shù)啊,一共7個(gè),其中6個(gè)有參的構(gòu)造函數(shù),1個(gè)有參的構(gòu)造函數(shù),所有的構(gòu)造函數(shù)都是public的,為了大家更好的理解,我將這些構(gòu)造函數(shù)編號如下:
- ① public Handler()
- ② public Handler(Callback callback)
- ③ public Handler(Looper looper)
- ④ public Handler(Looper looper, Callback callback)
- ⑤ public Handler(boolean async)
- ⑥ public Handler(Callback callback, boolean async)
- ⑦ public Handler(Looper looper, Callback callback, boolean async)
上面的7個(gè)Handler的構(gòu)造函數(shù)大體上可以分為兩大類:
- 兩個(gè)參數(shù)的Handler構(gòu)造函數(shù)
- 三個(gè)參數(shù)的Handler構(gòu)造函數(shù)
4.1 兩個(gè)參數(shù)的Handler構(gòu)造函數(shù)
這里說一下 ① ② ⑤ ⑥ 這四個(gè)是"兩個(gè)參數(shù)的Handler構(gòu)造函數(shù)",為什么這么說,大家可以看下源碼
4.1.1構(gòu)造函數(shù)①,代碼在Handler.java的 113行
/**
* Default constructor associates this handler with the {@link Looper} for the
* current thread.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*/
public Handler() {
this(null, false);
}
他內(nèi)部其實(shí)是調(diào)用的構(gòu)造函數(shù)⑥,只不過第一個(gè)入?yún)閚ull,第二個(gè)參數(shù)為false
4.1.2 構(gòu)造函數(shù)②,代碼在Handler.java的 127行
/**
* Constructor associates this handler with the {@link Looper} for the
* current thread and takes a callback interface in which you can handle
* messages.
*
* If this thread does not have a looper, this handler won't be able to receive messages
* so an exception is thrown.
*
* @param callback The callback interface in which to handle messages, or null.
*/
public Handler(Callback callback) {
this(callback, false);
}
他內(nèi)部其實(shí)是調(diào)用的構(gòu)造函數(shù)⑥,只不過第一個(gè)入?yún)閏allback,第二個(gè)參數(shù)為false
4.1.3 構(gòu)造函數(shù)⑤,代碼在Handler.java的 167行
/**
* Use the {@link Looper} for the current thread
* and set whether the handler should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
public Handler(boolean async) {
this(null, async);
}
他內(nèi)部其實(shí)是調(diào)用的構(gòu)造函數(shù)⑥,只不過第一個(gè)入?yún)閚ull,第二個(gè)參數(shù)為async
綜上所述我們知道 構(gòu)造函數(shù)① ② ⑤ ,歸根結(jié)底都是調(diào)用的是構(gòu)造函數(shù)⑥,那我們就來看下構(gòu)造函數(shù)⑥
4.1.4 構(gòu)造函數(shù)⑥,代碼在Handler.java的 188行
/**
* Use the {@link Looper} for the current thread with the specified callback interface
* and set whether the handler should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> klass = getClass();
//如果是匿名類、內(nèi)部類、局不類(方法內(nèi)部),且沒有聲明為STATIC,則存在內(nèi)存泄露風(fēng)險(xiǎn),所以要打印日志提醒開發(fā)者
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());
}
}
//獲取當(dāng)前線程的Looper。
mLooper = Looper.myLooper();
//如果當(dāng)前線程沒有Looper,則說明沒有調(diào)用Looper.prepare(),拋異常
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
//把Looper的Queue賦值給Handler的mQueue
mQueue = mLooper.mQueue;
// mCallback 賦值
mCallback = callback;
// mAsynchronous 賦值
mAsynchronous = async;
}
老規(guī)矩,先來看下注釋,簡單翻譯如下:
- 使用當(dāng)前線程的Looper,使用這個(gè)指定的Callback接口,并且設(shè)置這個(gè)handler是否是異步的。
- 除非在構(gòu)造函數(shù)設(shè)置為異步的,否則默認(rèn)的的Handler是同步的。
- 異步消息相對于同步消息的而言的,表示消息不會(huì)受到中斷或者事件的影響其全局順序。異步消息是不受到MessageQueue.enqueueSyncBarrier(long)的同步障礙影響。
通過上面代碼我們我們知道
- Handler默認(rèn)采用的是當(dāng)前線程TLS中的Looper對象,只要執(zhí)行了Looper.prepare()方法,就可以可以獲取有效的Looper對象,同時(shí)我們上面說了Looper的構(gòu)造函數(shù)關(guān)聯(lián)了MessageQueue和Thread。而在Handler的構(gòu)造函數(shù)里面Handler里面的MessageQueue即是Looper的MessageQueue。
所以在同一個(gè)線程里面(已經(jīng)調(diào)用了Looper.prepare()),Handler里面的MessageQueue和的Looper的MessageQueue指向了同一個(gè)對象。
所以我們也說這這個(gè)方法讓Handler對象和Looper對象綁定在一起了。
上面提到了Callback,是個(gè)什么?讓我們來看下
代碼在Handler.java的 80行
/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
*
* @param msg A {@link android.os.Message Message} object
* @return True if no further handling is desired
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
簡單翻譯一下:
當(dāng)你實(shí)例化Handler的時(shí)候可以使用Callback接口,這樣可以避免你自己去去實(shí)現(xiàn)Handler的子類
有點(diǎn)復(fù)雜,大家怎么理解?大家平時(shí)寫Handler不是一般是寫一個(gè)匿名內(nèi)部類居多吧,如下:
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
}
};
如果存在一個(gè)回調(diào)的需求,就可以直接使用Callback了,就不用去實(shí)現(xiàn)Handler的子類了。
4.2 三個(gè)參數(shù)的Handler構(gòu)造函數(shù)
這里說一下③、④、⑦ 這三個(gè)是"三個(gè)參數(shù)的Handler構(gòu)造函數(shù)",為什么這么說,依舊看下源碼
4.2.1構(gòu)造函數(shù)③,代碼在Handler.java的 136行
/**
* Use the provided {@link Looper} instead of the default one.
*
* @param looper The looper, must not be null.
*/
public Handler(Looper looper) {
this(looper, null, false);
}
他內(nèi)部其實(shí)是調(diào)用的構(gòu)造函數(shù)⑦,只不過第一個(gè)入?yún)閘ooper,第二個(gè)參數(shù)為null,第三個(gè)參數(shù)為false。
4.2.2構(gòu)造函數(shù)④,代碼在Handler.java的 147行
/**
* Use the provided {@link Looper} instead of the default one and take a callback
* interface in which to handle messages.
*
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
*/
public Handler(Looper looper, Callback callback) {
this(looper, callback, false);
}
他內(nèi)部其實(shí)是調(diào)用的構(gòu)造函數(shù)⑦,只不過第一個(gè)入?yún)閘ooper,第二個(gè)參數(shù)為callback,第三個(gè)參數(shù)為false。
4.2.3構(gòu)造函數(shù)⑦,代碼在Handler.java的 227行
/**
* Use the provided {@link Looper} instead of the default one and take a callback
* interface in which to handle messages. Also set whether the handler
* should be asynchronous.
*
* Handlers are synchronous by default unless this constructor is used to make
* one that is strictly asynchronous.
*
* Asynchronous messages represent interrupts or events that do not require global ordering
* with respect to synchronous messages. Asynchronous messages are not subject to
* the synchronization barriers introduced by {@link MessageQueue#enqueueSyncBarrier(long)}.
*
* @param looper The looper, must not be null.
* @param callback The callback interface in which to handle messages, or null.
* @param async If true, the handler calls {@link Message#setAsynchronous(boolean)} for
* each {@link Message} that is sent to it or {@link Runnable} that is posted to it.
*
* @hide
*/
public Handler(Looper looper, Callback callback, boolean async) {
mLooper = looper;
mQueue = looper.mQueue;
mCallback = callback;
mAsynchronous = async;
}
老規(guī)矩,先來看下注釋,簡單翻譯如下:
- 不使用默認(rèn)的Looper,使用由第一個(gè)入?yún)⑻峁┑腖ooper,并采取回調(diào)接口Callback來處理消息,同時(shí)也可以設(shè)置是否是異步的。
- Handler默認(rèn)是同步的,如果在構(gòu)造函數(shù)里面設(shè)置了異步,才會(huì)變成異步的。
- 異步消息相對于同步消息的而言的,表示消息不會(huì)受到中斷或者事件的影響其全局順序。異步消息是不受到MessageQueue.enqueueSyncBarrier(long)的同步障礙影響。
通過上面代碼我們我們知道
- 首先根據(jù)給定的Looper賦值本地變量mLooper和mQueue。這樣實(shí)現(xiàn)了Handler和Looper的關(guān)聯(lián)
4.3 Handler構(gòu)造函數(shù)總結(jié)
綜合7個(gè)構(gòu)造函數(shù)我們發(fā)現(xiàn)其實(shí)構(gòu)造函數(shù)的本質(zhì)都是給下面四個(gè)本地變量賦值mLooper、mQueue、mCallback、mAsynchronous。那我們就一次分析下:
- 1、如果在構(gòu)造函數(shù)中沒有給出Looper,則使用默認(rèn)的Looper,通過Looper.mQueue來給mQueue賦值,實(shí)現(xiàn)Handler、Looper、MessageQueue三者綁定。
-通過構(gòu)造函數(shù)來設(shè)置Callback的回調(diào)接口,不設(shè)置則為null
-通告mAsynchronous設(shè)控制是同步的還是異步的,而mAsynchronous的值默認(rèn)是false的,這個(gè)mAsynchronous可以通過構(gòu)造函數(shù)來設(shè)置。
總結(jié)如下:

有同學(xué)說圖片看不清,按我就弄個(gè)表格
| Hander本地變量 | ① Handler() | ② Handler(Callback) | ③ Handler(Looper) | ④ Handler(Looper, Callback) | ⑤ Handler(boolean) | ⑥ Handler(Callback, boolean) | ⑦ Handler(Looper,Callback, boolean) |
|---|---|---|---|---|---|---|---|
| mLooper(Looper對象) | Looper.myLooper() | Looper.myLooper() | looper | looper | Looper.myLooper() | Looper.myLooper() | looper |
| mQueue(MessageQueue對象) | null | callback | null | callback | null | callback | callback |
| mAsynchronous(boolean類型) | false | false | false | false | async | async | async |
四、 主線程的Looper的初始化
上面說了很多,那么主線程的Looper是什么時(shí)候初始化的那?是在系統(tǒng)啟動(dòng)的時(shí)候,初始化的。
代碼在ActivityThread.java 5401行
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
AndroidKeyStoreProvider.install();
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
/*** 重點(diǎn) */
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
/*** 重點(diǎn) */
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
PS:這里補(bǔ)充一個(gè)概念A(yù)ctivityThread不是一個(gè)thread,ActivityThread是一個(gè)類,大家仔細(xì)看他的源代碼ActivityThread并沒有實(shí)現(xiàn)Thread,大家千萬不要跑偏了。
通過上面的代碼,我們發(fā)現(xiàn)
- 首先調(diào)用了Looper的靜態(tài)方法prepareMainLooper()給主線程綁定一個(gè)Looper,同時(shí)設(shè)置Looper對應(yīng)的MessageQueue對象的mQuitAllowed為false,則該messageQueue是不能退出的。
- 其次調(diào)用Looper.loop();開啟循環(huán)
通過上面兩個(gè)步驟開啟了主線程的Hanlder機(jī)制