Looper,Handler,MessageQueue,Message之間的關係

Android異步消息機制架構:

Android異步消息處理架構,其實沒那麼複雜。簡單來講就是looper對象擁有messagequeue,而且負責從messagequeue中取出消息給handler來處理。同時handler又負責發送messagelooper,由loopermessage添加到messagequeue尾部。就一個圈兒。下面給出圖解:android

因此很明顯handlerlooper是來聯繫在一塊兒的。須要說明的是,多個message能夠指向同一個handler,多個handler也能夠指向同一個looper。還有一點很重要,普通的線程是沒有looper的,若是須要looper對象,那麼必需要先調用Looper.prepare()方法,並且一個線程只能有一個looper。調用完之後,此線程就成爲了所謂的LooperThread,若在當前LooperThread中建立Handler對象,那麼此Handler會自動關聯到當前線程的looper對象,也就是擁有looper的引用。網絡

Looper

Looper就是一個管理messagequeue的類。下面是這個類的源碼。架構

public class Looper {
    ......
    private static final ThreadLocal sThreadLocal = new ThreadLocal();
    final MessageQueue mQueue;//擁有的消息隊列
    ......
    /**
     * 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()}.
     */
    //建立新的looper對象,並設置到當前線程中
    public static final void prepare() {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper());
    }
    ·····
    /**
     * Return the Looper object associated with the current thread.  Returns
     * null if the calling thread is not associated with a Looper.
     */
    //獲取當前線程的looper對象
    public static final Looper myLooper() {
        return (Looper) sThreadLocal.get();
    }

    private Looper() { 
        mQueue = new MessageQueue(); 
        mRun = true; 
        mThread = Thread.currentThread();
    } 
          ......
}

調用完Looper.prepare()以後,在當前的線程建立的Handler才能擁有當前線程的looper。而後調用loop()來開啓循環,處理message。下面是Looper類下的loop方法部分源碼:less

public static void loop() {
    final Looper me = myLooper();//獲取looper對象
    if (me == null) {
        //若爲空則說明當前線程不是LooperThread,拋出異常
        throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
    }
    final MessageQueue queue = me.mQueue;
    獲取消息隊列
    .....
    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
        //打印log,說明開始處理message。msg.target就是Handler對象
        Printer logging = me.mLogging;
        if (logging != null) {
            logging.println(">>>>> Dispatching to " + msg.target + " " +
                    msg.callback + ": " + msg.what);
        }

        //重點!!!開始處理message,msg.target就是Handler對象
        msg.target.dispatchMessage(msg);//dispatchMessage:發送消息

        //打印log,處理message結束
        if (logging != null) {
            logging.println("<<<<< Finished to " + msg.target + " " + msg.callback);
        }
        .....
    }
}

是一個大的循環,不斷從消息隊列出取出消息。而後調用一個很關鍵的方法msg.target.dispatchMessage(msg)開始處理消息。msg.target就是message對應的handlerlooper對象管理MessageQueue,從中取出message分配給對應的handler來處理。異步

Message

Message 就是一些須要處理的事件,好比訪問網絡、下載圖片、更新ui界面什麼的。Message擁有幾個比較重要的屬性。async

         public int what 標識符,用來識別messageide

         public int arg1,arg2 能夠用來傳遞一些輕量型數據如int之類的函數

         public Object obj Message自帶的Object類字段,用來傳遞對象oop

         Handler target 指代此message對象對應的Handlerpost

若是攜帶比價複雜性的數據,建議用Bundle封裝,值得注意的地方是,雖然Message的構造方法是公有的,可是不建議使用。最好的方法是使用Message.obtain()或者Handler.obtainMessage() 能更好的利用循環池中的對象。通常不用手動設置target,調用Handler.obtainMessage()方法會自動的設置Messagetarget爲當前的Handler。獲得Message以後能夠調用sendToTarget(),發送消息給HandlerHandler再把消息放到messagequeue的尾部。這個方法的源碼以下:

/**
 * 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);//此處的target是message對應的Handler.
}

Handler

它的構造函數以下:

/**
 * 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);
}

/**
 * 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);
}

/**
 * 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);
}

/**
 * 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);
}

/**
 * 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);
}

/**
 * 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();
        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;
}

/**
 * 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;
}looperloopermessagequeue

要經過Handler來處理事件,能夠重寫handleMessage(Message msg),也能夠直接經過post(Runnable r)來處理。這兩個方法都會在looper循環中被調用。

loop循環中處理信息的msg.target.dispatchMessage(msg)方法源碼:

public void dispatchMessage(Message msg) {
    //注意!這裏先判斷message的callback是否爲空,不然就直接處理message的回調函數
    
   if (msg.callback!= null) {  //這裏的callback就是上面的Runnable
        handleCallback(msg);
    } else {
        if (mCallback != null) {
            //正是在這調用咱們日常重寫handleMessage
            if (mCallback.handleMessage(msg)) {
                return;
            }
        }
        handleMessage(msg);
    }
}

首先判斷是否用的是handler的post方法,若是是就執行r裏面run()方法的代碼,不然就判斷handler的構造函數是否初始化了CallBack,是的話就會執行這個接口裏面handleMessage(msg)方法,;若是放回的是false,最後就會調用handleMessage(msg)(創建handler時重寫的方法,若是沒有重寫,就什麼都不會執行)。下面是handler的post方法的源碼:

/**
 * Causes the Runnable r to be added to the message queue.
 * The runnable will be run on the thread to which this handler is 
 * attached. 
 *  
 * @param r The Runnable that will be executed.
 * 
 * @return Returns true if the Runnable was successfully placed in to the 
 *         message queue.  Returns false on failure, usually because the
 *         looper processing the message queue is exiting.
 */
public final boolean post(Runnable r)
{
   return  sendMessageDelayed(getPostMessage(r), 0);//發送消息
}

上面源碼中getPostMessage(r)方法的源碼:

private static Message getPostMessage(Runnable r) {
    Message m = Message.obtain();
    m.callback = r;  //就是上面的msg.callback,若是調用了handler的post方法,它就會不爲空。
    return m;
}

上面的 if (msg.callback!= null) { //這裏的callback就是上面的Runnable handleCallback(msg); }的handleCallback(msg)源碼:(就是運行run方法裏面的代碼)

private static void handleCallback(Message message) {
    message.callback.run();
}

而 if (mCallback.handleMessage(msg)) { return; }中的handleMessage(msg)源碼以下:

/**
 * 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);
}

因此如今知道loop循環中處理信息的msg.target.dispatchMessage(msg)方法裏面的代碼了吧。

相關文章
相關標籤/搜索