接上一篇分析,正如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類的分析就到這了。。。(因爲本人水平有限,歡迎批評指正)