Android訊息處理機制、Hanlder機制(Handler、Looper、MessageQueue和Message)
·前言
長久以來,我使用Hanlder僅限於它的基本使用:post 和 sendMessage而對於Hanlder的原理和訊息處理機制並不清楚。找了兩篇比較深入的部落格:
學習了一下,又對照了原始碼,小有收穫,俗話說“好記性不如爛筆頭”,所以做一下筆記,總結一下,方便以後回顧。
·Android是訊息驅動的
AngelDevil的部落格的部落格中指出Android是訊息驅動的,這一點,看一下類ActivityThread就一目瞭然了。
public final class ActivityThread { //…… final ApplicationThread mAppThread = new ApplicationThread(); //…… final H mH = new H(); //…… final Handler getHandler() { return mH; } //…… private class ApplicationThread extends ApplicationThreadNative {//……} //…… private class H extends Handler {//……} //…… public static void main(String[] args) { //…… 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); Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } }
原始碼中找到了入口方法main(),從Looper.prepareMainLooper();這一行看起,到Looper.looper();我們都知道,main()方法是程式的入口,方法裡面就是主執行緒,從Looper.prepareMainLooper()到Looper.looper(),表明開啟了輪詢器,其間不斷的進行訊息的傳送和處理,所以說Android確實是“訊息驅動的”。ActivityThread thread = new ActivityThread():表明在入口方法main()中建立了一個ActivityThread自己的物件,並通過程式碼
獲得ActivityThread內部的Handler,而ActivityThread原始碼中有這這幾行程式碼:if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); }
final ApplicationThread mAppThread = new ApplicationThread(); final H mH = new H(); final Handler getHandler() { return mH; } private class ApplicationThread extends ApplicationThreadNative {//……} private class H extends Handler {//……}
getHanlder就是H,H繼承於Handler,而H(extends Handler)的handleMessage(){}中接受的都是一些系統訊息。
也就是說,在主執行緒中,有一個Looper輪詢器,在Looper.prepareMainLooper()和Looper.loop()之間建立了ActivityThread例項,並獲得了ActivityThread內部的Handler例項,相當於在Looper的兩個方法中間建立了Hanlder。Android正是通過這個Handler進行的訊息傳遞。
·Looper輪詢器
下面看一下Android原始碼中提供的Looper典型使用
/** * …… * This is a typical example of the implementation of a Looper thread, * using the separation of {@link #prepare} and {@link #loop} to create an * initial Handler to communicate with the Looper. *//這是一個Looper執行緒實現的典型案例,使用Looper.prepare()和Looper.loop()中間被隔開的部分建立 *//和初始化Handler,以便與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(); * } * } */public final class Looper {//……}
正好與上面ActivityThead類中的用法相對應,只不過一個在主執行緒中(main()中),一個在子執行緒中。其本質用法是一樣的。下面是Looper的原始碼:
/**
* 這個類用於為一個執行緒執行一個訊息迴圈。預設的執行緒並沒有一個訊息迴圈與它們相關聯;
* 線上程中呼叫此類的prepare()方法來建立一個訊息迴圈並且執行這個迴圈,然後呼叫Loop()
* 來使訊息迴圈處理訊息直到這個迴圈被終止。
*
* 大多數與訊息迴圈的互動是通過Handler類來實現的。
*
* 這是一個Looper執行緒實現的典型案例,通過使用Looper.prepare()和Looper.loop()中間被隔開的部分建立
* 和初始化Handler,以便與Looper進行通訊。
* This is a typical example of the implementation of a Looper thread,
* using the separation of {@link #prepare} and {@link #loop} to create an
* initial Handler to communicate with the Looper.
*
* <pre>
* 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();
* }
* }</pre>
*/
public final class Looper {
private static final String TAG = "Looper";
// sThreadLocal.get() 將返回null,除非你已經呼叫了prepare().
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
private static Looper sMainLooper; // guarded by Looper.class
final MessageQueue mQueue;
final Thread mThread;
private Printer mLogging;
/** 將當前執行緒初始化為一個輪詢器(looper)。(也就是在當前執行緒中維持一個輪詢器)
* 這樣你就可以建立handler,handler之後會在開始輪詢之前引用這個輪詢器。要確保在呼叫
* 這個方法後呼叫{@link #loop()}方法,並且呼叫{@link #quit()}方法結束它。
*/
public static void prepare() {
prepare(true);
}
/**
* 這個方法中建立了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));
}
/**
* 將當前執行緒初始化為一個輪詢器(looper), 並標記為一個應用的主輪詢器。
* 應用的朱輪詢器由Android環境建立(在ActivityThread#main()中被呼叫),
* 所以你不需要自己呼叫這個方法。可以看:{@link #prepare()}。
*/
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
/**
* 返回應用的主輪詢器(looper),它存在於應用的主執行緒。
*/
public static Looper getMainLooper() {
synchronized (Looper.class) {
return sMainLooper;
}
}
/**
* 在當前執行緒中執行(輪詢)訊息佇列。確保呼叫{@link #quit()}方法結束迴圈。
*/
public static void loop() {
//獲取當前執行緒的Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//獲取Looper中的訊息佇列
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;
}
// This must be in a local variable, in case a UI event sets the logger
Printer logging = me.mLogging;
if (logging != null) {
logging.println(">>>>> Dispatching to " + msg.target + " " +
msg.callback + ": " + msg.what);
}
//###通過message的target(Handler)分發處理訊息
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.
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);
}
msg.recycleUnchecked();
}
}
/**
* 返回與當前執行緒關聯的Looper物件,如果當前執行緒未關聯Looper,返回null。
*/
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
/**
* 返回與當前執行緒關聯的 {@link MessageQueue} 物件。這個方法必須在執行著Looper的執行緒中
* 呼叫,否則會丟擲空指標異常。
*/
public static @NonNull MessageQueue myQueue() {
return myLooper().mQueue;
}
/**
* 私有構造方法。
* 其中建立了訊息佇列(MessageQueue)。獲取了當前執行緒。
* 在prepare()方法中呼叫建立例項。可以通過myLooper()方法獲取looper例項。
*/
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
/**
* 停止當前輪詢器。
* <p>
* 使{@link #loop} 停止,不再處理訊息佇列中的任何訊息。
* </p><p>
* 輪詢器停止(輪詢)後,任何嘗試傳送訊息到佇列都將失敗。
* 例如,{@link Handler#sendMessage(Message)} 方法將會返回false。
* </p><p class="note">
* 使用這個方法可能不安全,因為一些訊息可能在輪詢器結束之前沒有被分發處理。
* 考慮使用{@link #quitSafely} 代替,以確保所有待完成的工作能被井井有條地完成。
* </p>
*/
public void quit() {
mQueue.quit(false);
}
/**
* 安全停止當前輪詢器。
* <p>
* 一旦訊息佇列中所有餘下的到期的訊息被分發處理,就使迴圈{@link #loop} 停止。
* 然而,還有一定時間到期的延遲訊息不會在迴圈終止之前分發處理。
* </p><p>
* 輪詢器停止(輪詢)後,任何嘗試傳送訊息到佇列都將失敗。
* 例如,{@link Handler#sendMessage(Message)} 方法將會返回false。
* </p>
*/
public void quitSafely() {
mQueue.quit(true);
}
/**
* 獲得與這個輪詢器關聯的執行緒。
*
* @return 輪詢器的執行緒
*/
public @NonNull Thread getThread() {
return mThread;
}
/**
* 獲得輪詢器的訊息佇列。
*
* @return 輪詢器的訊息佇列
*/
public @NonNull MessageQueue getQueue() {
return mQueue;
}
//......
}
從Looper原始碼中可以得知:① Looper的構造方法被私有化,只能Looper能建立自己物件,而且在構造方法中,建立MessageQueue例項,獲得當前執行緒。② 在Looper的prepare()方法中建立了一個Looper物件,並且設定給sThreadLocal(ThreadLocal<Looper>),sThreadLocal.set(new Looper(quitAllowed));③ Looper.prepare()在一個執行緒中只能例項化一次,否則將丟擲異常④ Looper的loop()方法中,要從當前Looper(Looper me = myLooper())中獲得它的MessageQueue,並迴圈取出Message進行處理。 *myLooper()方法獲得設定給ThreadLocal中的Looper,sThreadLocal.get()。Looper的prepare()方法中呼叫了ThreadLocal的set()方法,myLooper()中呼叫了ThreadLocal的get()方法,下面看ThreadLocal的get()和set()方法:
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null)
return (T)e.value;
}
return setInitialValue();
}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
//獲取執行緒t的ThreadLocalMap
ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}
//為執行緒t的(ThreadLocalMap)threadLocals賦值
void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}
set()方法將looper設定給當前執行緒,get()方法從當前執行緒中獲得looper。小結一下:①Looper通過prepare()方法,建立Looper自己的物件,同時建立了一個訊息佇列(MessageQueue),並通過ThreadLocal的set()方法設定給了當前執行緒(其實是當前執行緒的ThreadLocalMap的Entry的value);②Looper通過myLooper(),其實是通過sThreadLocal(ThreadLocal<Looper>)的get()方法從當前執行緒中獲得Looper。③Looper的loop()方法中,獲得當前執行緒的Looper,並獲得Looper的MessageQueue,然後迴圈取出訊息,交給Message的target(傳送Message的Hanlder)分發處理。 *我們都知道Activity屬於應用的主執行緒,在Activity中建立的Hanlder(不指定Looper),其實是在上面main()中的Looper.prepareMainLooper()和Looper.loop()之間,與Looper的典型使用,一模一樣。Hanlder
看一下Hanlder的構造方法:下面是兩個主要構造方法的原始碼:
public Handler(Callback callback, boolean async) {
if (FIND_POTENTIAL_LEAKS) {
final Class<? extends Handler> 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;
}
從Handler(Callback callback, boolean async)的mLooper = Looper.myLooper()處往下看,這是要獲得當前執行緒的Looper,如果mLooper == null,就丟擲執行時異常mLooper = Looper.myLooper();if (mLooper == null) {throw new RuntimeException(//不能在沒有呼叫Looper.prepare()的執行緒裡建立handler."Can’t create handler inside thread that has no called Looper.prepare()");}這兩個構造方法中,一個是從當前執行緒取出與之關聯的Looper,另一個要傳入一個Looper,所以說要線上程中建立Handler例項,需要一個Looper。Handler傳送訊息
下面是Handler傳送訊息內部呼叫流程發現Handler傳送訊息方法中最終呼叫的是sendMessageAtTime()方法,下面是訊息傳送的原始碼:
public final boolean sendMessage(Message msg)
{
return sendMessageDelayed(msg, 0);
}
public final boolean sendEmptyMessage(int what)
{
return sendEmptyMessageDelayed(what, 0);
}
public final boolean sendEmptyMessageDelayed(int what, long delayMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageDelayed(msg, delayMillis);
}
public final boolean sendEmptyMessageAtTime(int what, long uptimeMillis) {
Message msg = Message.obtain();
msg.what = what;
return sendMessageAtTime(msg, uptimeMillis);
}
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);
}
public final boolean post(Runnable r){
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postAtTime(Runnable r, long uptimeMillis){
return sendMessageAtTime(getPostMessage(r), uptimeMillis);
}
public final boolean postAtTime(Runnable r, Object token, long uptimeMillis){
return sendMessageAtTime(getPostMessage(r, token), uptimeMillis);
}
public final boolean postDelayed(Runnable r, long delayMillis){
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
private static Message getPostMessage(Runnable r) {
Message m = Message.obtain();
m.callback = r;
return m;
}
private static Message getPostMessage(Runnable r, Object token) {
Message m = Message.obtain();
m.obj = token;
m.callback = r;
return m;
}
private static void handleCallback(Message message) {
message.callback.run();
}
我們可以看出,① 其他傳送訊息的方法最後都呼叫了sendMessageAtTime()方法,然後返回了enqueueMessage()方法② 傳送空訊息(sendEmptyMessage)時,其實建立了訊息實體,只是沒有訊息內容(資料)③ post系列方法看似傳送的是Runnable,但最終呼叫sendMessageAtTime(Message msg, long uptimeMillis),而這個方法第一個引數是一個Message,其實發送的還是Message,看一下getPostMessage()會發現,裡面建立了訊息,並將Runnable賦值給message的callback。而在handler的dispatchMessage()中呼叫了(if (msg.callback != null))handleCallback(msg),而handleCallback()中運行了Runnable(message.callback.run())下面看一下此方法原始碼:private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
msg.target = this;
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
在這個方法中需要注意 1.msg.target = this 這是將當前handler賦值給了Message的target,而在之後Looper的loop()方法中,從MessageQueue中迴圈取出Message(msg)後, 呼叫msg.target.dispatchmessage(msg)來處理這個訊息。 2.queue.enqueueMessage(msg, uptimeMillis) queue由sendMessageAtTime方法傳傳參而來,最終來自handler構造方法的myLooper()方法,也就是當前handler所線上程的Looper管理的MessageQueue。 也就是說,handler傳送訊息到當前執行緒的Looper的訊息佇列裡。Message
下面看一下Message部分的原始碼:public final class Message implements Parcelable {
public int what;
public int arg1;
public int arg2;
public Object obj;
//......
/*package*/ Handler target;
/*package*/ Runnable callback;
// sometimes we store linked lists of these things
/*package*/ Message next;
private static final Object sPoolSync = new Object();
private static Message sPool;
private static int sPoolSize = 0;
private static final int MAX_POOL_SIZE = 50;
private static boolean gCheckRecycle = true;
/**
* Return a new Message instance from the global pool. Allows us to
* avoid allocating new objects in many cases.從全域性池中返回一個新的訊息例項。
* 使我們在很多情況下避免分配新的物件。
*/
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();
}
//......
/**
* Return a Message instance to the global pool.回收一個訊息放到全域性池。
* <p>
* You MUST NOT touch the Message after calling this function because it has
* effectively been freed. It is an error to recycle a message that is currently
* enqueued or that is in the process of being delivered to a Handler.
* 呼叫這個方法後你就不能再用Message,因為它已經被有效釋放。回收一個正在列隊或正在被
* 分配給Hanlder的過程中的Message是錯誤的。
* </p>
*/
public void recycle() {
if (isInUse()) {
if (gCheckRecycle) {
throw new IllegalStateException("This message cannot be recycled because it "
+ "is still in use.");
}
return;
}
recycleUnchecked();
}
/**
* Recycles a Message that may be in-use.
* Used internally by the MessageQueue and Looper when disposing of queued Messages.
*/
void recycleUnchecked() {
// Mark the message as in use while it remains in the recycled object pool.
// Clear out all other details.
flags = FLAG_IN_USE;
what = 0;
arg1 = 0;
arg2 = 0;
obj = null;
replyTo = null;
sendingUid = -1;
when = 0;
target = null;
callback = null;
data = null;
synchronized (sPoolSync) {
if (sPoolSize < MAX_POOL_SIZE) {
next = sPool;
sPool = this;
sPoolSize++;
}
}
}
//......
public void setTarget(Handler target) {
this.target = target;
}
public Handler getTarget() {
return target;
}
//......
/**
* Sends this Message to the Handler specified by {@link #getTarget}.
* Throws a null pointer exception if this field has not been set.
*/
public void sendToTarget() {
target.sendMessage(this);
}
/** Constructor (but the preferred way to get a Message is to call {@link #obtain() Message.obtain()}).
* 構造器 (但是獲得一個Message的首選方式是呼叫Message.obtain())
*/
public Message() {
}
//......
}
從Message部分原始碼中可以看出: 1. 建立Message例項,首選Message.obtain() 2. Message的target確實是一個Handler,而Message的callback是一個Runnable 3.Message內部儲存了一個全域性快取的訊息池,我們可以用obtain從快取池獲得一個訊息,Message使用完後系統會呼叫recycle回收,如果自己new很多Message,每次使用完後不能及時回收,會佔用很多記憶體的。Handler處理訊息
看一下Looper的loop()方法的原始碼:public static void loop() {
final Looper me = myLooper();//獲得當前執行緒的Looper
if (me == null) {//如果為null,丟擲執行時異常("沒有Looper;執行緒中沒有呼叫Looper.prepare()
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread."
}
final MessageQueue queue = me.mQueue; //從Looper中獲得訊息佇列
// ……
//開始無限迴圈
for (;;) {
//不斷從訊息佇列中取出訊息(Message)
Message msg = queue.next(); // might block 可能阻斷
if (msg == null) {
// No message indicates that the message queue is quitting. 如果沒有訊息標識(沒有
return;
}
//……
try { //msg.target其實是一個Hanlder,Hanlder傳送訊息時,會把當前這個handler作為target
msg.target.dispatchMessage(msg);//Hanlder分發訊息
} finally {
//……
}
//……
msg.recycleUnchecked();
}
}
程式碼,msg.target.dispatchMessage(msg),表明Message的target處理了訊息,也就是傳送訊息的handler處理了訊息(誰傳送,誰處理),也是這個Looper所線上程的Handler處理了訊息。所以說,Looper.prepare()中建立了訊息佇列(MessageQueue),並與當前執行緒關聯;Looper.loop()獲得當前執行緒的Looper並迴圈遍歷其管理的MessageQueue(),用Message自己的target處理訊息。這個target就是當前執行緒Looper兩個方法之間建立的handler物件。我們就知道了,Looper的loop()方法是取出訊息並處理訊息的場所,而真正處理訊息的物件,還是傳送訊息的handler。Looper的loop()方法中使用了msg.target.dispatchMessage(msg),也就是Handler的dispatchMessage()方法,下面看一下handler的訊息分發處理的原始碼:/**
* Callback interface you can use when instantiating a Handler to avoid
* having to implement your own subclass of Handler.
* 例項化一個handler時,為避免必須實現你自己的Hanlder的子類,你可以使用回撥介面。
*/
public interface Callback {
public boolean handleMessage(Message msg);
}
/**
* Subclasses must implement this to receive messages.//子類必須實現這個方法來接收訊息。
*/
public void handleMessage(Message 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);
}
}
private static void handleCallback(Message message) {
message.callback.run();
}
從原始碼可以看出,訊息分發處理有三層:① 當msg.callback !=null,也就是使用了handler的post系列方法傳送了訊息(將Runnable賦值給了message的callback),訊息由handleCallback()方法處理(message.callback.run())② 當mCallback != null,也就是handler設定了Callback,訊息就由handler的Callback的handleMessage()處理③ 當mCallback為空或Callback的handleMessage()處理完訊息表明還有訊息要處理,返回false,訊息由handler子類的實現方法handleMessage()處理。 *handler的Callback的原始碼註釋中指出,如果不想實現Handler的子類(必須實現handleMessage()方法處理訊息),可以設定CallBack回撥介面。·總結
1. 一個執行緒中要想建立Handler傳送處理訊息,要先呼叫Looper.prepare()和Looper.loop()來建立一個訊息佇列(MessageQueue)開啟一個輪詢器與執行緒關聯。
2. 在Looper的兩個方法中間建立Handler,handler建立時要拿到與當前執行緒關聯的輪詢器(Looper)和輪詢器管理的訊息佇列(MessageQueue)
3. Handler傳送訊息(Message)其實是傳送到了2中的訊息佇列(MessageQueue),傳送訊息同時,Handler將自己設定給Message的target
4. 訊息是在Looper的loop()方法中迴圈取出處理,最終由Message的target也就是傳送自己的handler處理。
Handler:
建立:在Looper.prepare()和Looper.loop()之間建立
作用:傳送訊息(Message)到所線上程關聯的輪詢器(Looper)的訊息佇列(MessageQueue),並將自己作為target設定給Message
處理訊息,由dispatchMessage()分發給①Callback的handleMessage()、②Handler的handleMessage()或③Handler的handleCallback()處理
Looper 輪詢器
建立:由自己的prepare()方法建立並關聯當前執行緒。
作用:Looper.perpare(),建立自己的例項同時建立一個MessageQueue,並將自己設定給當前執行緒
Looper.loop()從當前執行緒拿到Looper及其MessageQueue,迴圈遍歷MessageQueue,取出訊息,交給Message的target(傳送訊息的handler)處理
*Looper.myLooper():獲得當前執行緒所關聯的Looper。
MessageQueue 訊息佇列
建立:Looper的構造方法中建立,最終由Looper的prepare()方法建立
作用:接收handler傳送訊息時加入進來的訊息,將其放入佇列中,先入先出
Message 訊息
建立:優先用Message.obtain()獲取例項,Handler傳送訊息時建立,最終由MessageQueue管理
作用:攜帶訊息內容傳遞資料,或作為一個訊號(what)
注意:Message在被髮送時會將傳送它的Handler作為target,在使用Handler的post系列方法時,傳入的Runnable物件由Message的callback得到。