Android源碼分析之Handler

  接上一篇分析,正如Android doc所說,Handler主要有2方面用處:java

1. delay執行同一線程中的某個操做,也就是schedule message、runnable在將來的某一時刻執行;android

2. 給另一個線程發送message、runnable,讓某個操做在另外一個線程中執行。好比A線程只要能拿到B線程的less

handler就能經過此handler在A線程中經過post message、runnable,讓這些消息的處理髮生在B線程中,從而實現異步

線程間的通訊。AsyncTask就是經過在background線程中經過關聯UI線程的handler來向UI線程發送消息的。爲了看的async

更清楚些,這裏摘抄下Looper.java開頭處給的一個典型例子:ide

  * 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>

在這裏,別的線程能夠經過LooperThread.mHandler來實現和它的通訊。函數

  接下來一點點分析源碼,先看幾個相關的:oop

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

這個Callback接口裏只有一個handleMessage方法返回boolean值,在後面Handler的ctor會用到,通常狀況下都是null。這個接口的存在post

沒什麼特殊的含義,只是爲了讓你不extends Handler就能處理消息而已(正如此方法的doc所說),相似Thread和Runnable接口的關係。學習

接下來是dispatchMessage方法,咱們已經在上一篇分析Message的時候大概提到了。它的處理是若是message自身設置了callback,則

直接調用callback.run()方法,不然Callback接口的做用就顯現了;若是咱們傳遞了Callback接口的實現,即mCallback非空,則調用它處理

message,若是處理了(consumed)則直接返回,不然接着調用Handler本身的handleMessage方法,其默認實現是do nothing,若是你

是extends Handler,那麼你應該在你的子類中爲handleMessage提供本身的實現。

  接下來咱們首先看看Handler都有哪些關鍵的字段,源碼以下:

final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
final boolean mAsynchronous;

mQueue來自mLooper,mLooper要麼是在ctor中顯式指定的要麼是默認當前線程的,Handler關於Message、Runnable的全部處理都delegate給了mQueue;mCallback是用戶提供的Callback實現,默認是null;mAsynchronous表示Handler是不是異步的,默認是同步的。

  接下來咱們來看各類各樣的Handler的ctor(構造器):

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

咱們來看3個參數的版本,即Looper,Callback,boolean,默認looper是關聯的當前線程的,callback是null,async是false。固然你願意也能夠分別指定這3個值。關於ctor不須要贅述,看doc、comment就能夠很容易理解。

  接下來是一堆Handler的obtainMessage函數,其實現都是直接調用Message的靜態函數obtain,但相應的message的target字段都自動被設置成了當前的Handler對象。因爲Message的源碼已在上一篇中分析過了,這裏一帶而過。

  getPostMessage(Runnable r)之類的也很簡單,就是將runnable包裝成一個Message,其callback字段被設置成了runnable。

  接下來的一堆postxxx、sendxxx,最終會調用下面這個方法:

private boolean enqueueMessage(MessageQueue queue, Message msg, long uptimeMillis) {
        msg.target = this;
        if (mAsynchronous) {
            msg.setAsynchronous(true);
        }
        return queue.enqueueMessage(msg, uptimeMillis);
    }

在這裏,message的target被設置成當前的Handler,若是是異步的Handler,則設置message也爲異步的,而後入隊,uptimeMillis表示絕對時間戳。這裏須要提一下的是xxxAtFrontOfQueue方法,這個方法由於每次是將後來的message插在隊列的前頭,因此可能致使隊列中的其餘消息沒機會獲得處理(即飢餓),或得不到及時處理,因此說插隊是很差的,慎用。正如其方法doc中所說,其實在咱們的工做學習中,我也強烈推薦你們仔細看看相關類、方法的doc。我知道咱們這類人都不喜歡寫doc,因此既然能有doc那說明真的是必不可少的,挺重要的。

  接下來是removeCallbacks相關的,源碼:

/**
     * Remove any pending posts of Runnable r that are in the message queue.
     */
    public final void removeCallbacks(Runnable r)
    {
        mQueue.removeMessages(this, r, null);
    }

    /**
     * Remove any pending posts of Runnable <var>r</var> with Object
     * <var>token</var> that are in the message queue.  If <var>token</var> is null,
     * all callbacks will be removed.
     */
    public final void removeCallbacks(Runnable r, Object token)
    {
        mQueue.removeMessages(this, r, token);
    }

其實現也都是delegate給了mQueue,有一點須要注意下就是這些方法會remove掉全部的Runnable r,而不是第一個匹配的

(注意方法名中的s,是複數而不是單數),也就是說一次remove調用能夠remove掉以前好屢次post的同一個runnable,

若是以前post的runnable還在隊列中的話。

  removeMessages、hasMessages之類的方法挺簡單不過多解釋。

  Handler類的分析就到這了。。。(因爲本人水平有限,歡迎批評指正

相關文章
相關標籤/搜索