1. 程式人生 > >Android訊息處理機制、Hanlder機制(Handler、Looper、MessageQueue和Message)

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自己的物件,並通過程式碼
if (sMainThreadHandler == null) {
     sMainThreadHandler = thread.getHandler(); 
}
獲得ActivityThread內部的Handler,而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 {//……}

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得到。