什麼是Handler?windows
Android 的官方解釋:app
文檔分節1:A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue. Each Handler instance is associated with a single thread and that thread's message queue. When you create a new Handler, it is bound to the thread / message queue of the thread that is creating it -- from that point on, it will deliver messages and runnables to that message queue and execute them as they come out of the message queue.
這個解釋給咱們釋放出如下幾個信息:less
一 Handler能夠發送和處理兩種類型的事物:async
1,Message;ide
2,實現Runnable接口的對象oop
二,每一個Handler實例都會跟建立Handler的Thread及這個Thread下的MessageQueue相關聯。post
文檔分節2:There are two main uses for a Handler: (1) to schedule messages and runnables to be executed as some point in the future; and (2) to enqueue an action to be performed on a different thread than your own.
Handler主要有兩個做用:ui
1,能夠設定某個時間點去執行Message和Runnable對象this
2,能夠在不一樣的線程中去執行某項任務spa
文檔分節3:Scheduling messages is accomplished with the post(Runnable), postAtTime(Runnable, long), postDelayed(Runnable, long),sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long), and sendMessageDelayed(Message, long) methods. The post versions allow you to enqueue Runnable objects to be called by the message queue when they are received; the sendMessage versions allow you to enqueue a Message object containing a bundle of data that will be processed by the Handler's handleMessage(Message) method (requiring that you implement a subclass of Handler).
Handler主要提供了兩種方式來調度消息:
1,post方式:處理Runnable對象
2,sendmessage方式:在Message中放入Bundle data,這個消息會在Handler提供的handleMessage(Message)方法中去處理;
文檔分節4:When posting or sending to a Handler, you can either allow the item to be processed as soon as the message queue is ready to do so, or specify a delay before it gets processed or absolute time for it to be processed. The latter two allow you to implement timeouts, ticks, and other timing-basedbehavior.
When a process is created for your application, its main thread is dedicated to running a message queue that takes care of managing the top-level application objects (activities, broadcast receivers, etc) and any windows they create. You can create your own threads, and communicate back with the main application thread through a Handler. This is done by calling the same post or sendMessage methods as before, but from your new thread. Thegiven Runnable or Message will then be scheduled in the Handler's message queue and processed when appropriate.
1,咱們可讓handler立刻或者指定一個時間間隔發送消息;
2,當咱們的應用開啓時,UI線程會自動幫咱們建立好MessageQueue,咱們也能夠在本身定義的Thread中建立。
這些信息咱們如今只要稍微有個概念就好,一會進入Handler的深刻分析以後,天然就會清楚,咱們先來分析一下Handler的源碼:
先來看看Handler主要的成員變量:
final MessageQueue mQueue; final Looper mLooper; final Callback mCallback; final boolean mAsynchronous; IMessenger mMessenger;
咱們先粗略地看一下,Handler這個類裏面有MessageQueue,從名稱中咱們能夠猜想,這個就應該是消息隊列了,第二個成員變量:Looper,從名稱來看,應該是個推進消息循環的角色,第三個成員變量:Callback,應該是個回調的接口,剩下的兩個先暫時忽略,這三個比較重要的成員變量我們先混個眼熟,打個招呼就好,如今咱們來看一下這個類的構造方法,依次先從最簡潔的構造方法看起:
public Handler() { this(null, false); }
public Handler(Callback callback) { this(callback, false); }
public Handler(Looper looper) { this(looper, null, false); }
public Handler(Looper looper, Callback callback) { this(looper, callback, false); }
public Handler(boolean async) { this(null, async); }
1 public Handler(Callback callback, boolean async) { 2 if (FIND_POTENTIAL_LEAKS) { 3 final Class<? extends Handler> klass = getClass(); 4 if ((klass.isAnonymousClass() || klass.isMemberClass() || klass.isLocalClass()) && 5 (klass.getModifiers() & Modifier.STATIC) == 0) {
//想必你們對下面這句話不陌生吧?細心的朋友們會常常在開發環境中看到這句黃色警告(該Handler可能會致使內存泄漏),後面的系列咱們再給出解決這個警告的示例代碼 6 Log.w(TAG, "The following Handler class should be static or leaks might occur: " + 7 klass.getCanonicalName()); 8 }
9 } 10 11 mLooper = Looper.myLooper(); 12 if (mLooper == null) { 13 throw new RuntimeException(
//這個拋出的異常信息你們也可能一不當心就會看到 14 "Can't create handler inside thread that has not called Looper.prepare()"); 15 } 16 mQueue = mLooper.mQueue; 17 mCallback = callback; 18 mAsynchronous = async; 19 }
1 public Handler(Looper looper, Callback callback, boolean async) { 2 mLooper = looper; 3 mQueue = looper.mQueue; 4 mCallback = callback; 5 mAsynchronous = async; 6 }
我了個大去,稍微看去洋洋灑灑出現了7個構造方法,仔細看下,其實前面五種構造方法都調用到了最後兩種構造方法中的一種,那麼咱們就着重來看一下這兩個構造方法
public Handler(Callback callback, boolean async)的構造方法裏面都幹了些啥?
1,經過Looper的myLooper()方法,獲得一個Looper對象,將之傳給Handler的成員變量mLooper;
若是拿到的這個對象爲null,就會拋出異常,從異常的信息來看,說是沒有在建立Handler的時候去調用Looper的prepare()方法;
2,從獲得的Looper對象拿出MessageQueue對象,傳給Handler的成員變量mQueue;
3,將入參callback傳給Handler的成員變量mCallback;
看到這裏,朋友們可能會發現這個Looper看來是個重要角色啊,忍不住想去一窺究竟,先忍一忍,好戲老是在後頭,先來看一下另一個重要的構造方法
public Handler(Looper looper, Callback callback, boolean async)
其實這個方法作的就是上面那個構造方法的事情,只不過,mLooper,mQueue,mCallback都是在調用以前就已經建立好了,直接賦值而已
上面已經看了Handler這個類的成員變量,構造方法,那麼,咱們如今就來看一下這個類裏面都給外部提供了哪些接口和方法
public interface Callback { public boolean handleMessage(Message msg); }
原來Callback真的就是一個接口,提供了一個回調的方法 handleMessage(Message msg),這個方法的名字有點熟悉,是否是就是咱們常常見到的那個在新建立一個Handler的時候,須要覆蓋的方法呢?先帶着疑問往下看,
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
看到這個類的註解,你們立刻發現上面的疑問是本身多想了,兩個方法雖然同名,可是返回類型不一樣啊,原來這個方法纔是咱們常見的那個須要覆蓋的方法。
接着往下看,
在文章開頭的文檔分節3中,咱們知道,Handler主要提供了兩種方式來發送消息,一種是postXX方法,一種是sendMessageXX方法
果真,咱們看到了大量的post和sendmessage方法
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); }
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); }
細心的朋友們仔細一看,就能發現,其實不論是postXX仍是sendMessageXX方法,最終調用的都是sendMessageAtTime這個方法,postXX方法只是否是多調了getPostMessage()方法而已 ,那麼咱們就來看一下這個方法作了些什麼事情:
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; }
首先獲取一個Message,而後把Runnable對象傳遞給Message的callback變量,返回一個Message;
咱們在文章開頭中的Handler的官方文檔中提到這麼一句話
A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.
那麼,這裏的callback就是這個Runnable object了!
而後咱們接着看sendMessageAtTime到底作了些啥?關鍵的代碼就在最後一句:
return enqueueMessage(queue, msg, uptimeMillis);
從這個方法名中,咱們能夠知道它是讓這個消息入列,咱們來看一下它的具體實現:
1 boolean enqueueMessage(Message msg, long when) { 2 if (msg.target == null) { 3 throw new IllegalArgumentException("Message must have a target."); 4 } 5 if (msg.isInUse()) { 6 throw new IllegalStateException(msg + " This message is already in use."); 7 } 8 9 synchronized (this) { 10 if (mQuitting) { 11 IllegalStateException e = new IllegalStateException( 12 msg.target + " sending message to a Handler on a dead thread"); 13 Log.w("MessageQueue", e.getMessage(), e); 14 msg.recycle(); 15 return false; 16 } 17 18 msg.markInUse(); 19 msg.when = when; 20 Message p = mMessages; 21 boolean needWake; 22 if (p == null || when == 0 || when < p.when) { 23 // New head, wake up the event queue if blocked. 24 msg.next = p; 25 mMessages = msg; 26 needWake = mBlocked; 27 } else { 28 // Inserted within the middle of the queue. Usually we don't have to wake 29 // up the event queue unless there is a barrier at the head of the queue 30 // and the message is the earliest asynchronous message in the queue. 31 needWake = mBlocked && p.target == null && msg.isAsynchronous(); 32 Message prev; 33 for (;;) { 34 prev = p; 35 p = p.next; 36 if (p == null || when < p.when) { 37 break; 38 } 39 if (needWake && p.isAsynchronous()) { 40 needWake = false; 41 } 42 } 43 msg.next = p; // invariant: p == prev.next 44 prev.next = msg; 45 } 46 47 // We can assume mPtr != 0 because mQuitting is false. 48 if (needWake) { 49 nativeWake(mPtr); 50 } 51 } 52 return true; 53 }
分析第2行:msg.target,這個target指的是啥呢?咱們這裏先暫時無論,後來具體分析Message這個類的時候,咱們會分析到
分析第10行:mQuitting,若是這個變量爲true,那麼就會拋出一個異常,在後續的分析IntentService的時候,咱們會遇到這個異常,在這裏先有個印象;
分析第33-45行:這裏就是把消息按照消息的時間順序進行排列而已,即把消息隊列中的消息按照時間進行排序,並無執行真正的入列操做,那何時執行真正的入列操做呢?後面分析Looper這個類的時候,咱們會分析到
1 /** 2 * Handle system messages here. 3 */ 4 public void dispatchMessage(Message msg) { 5 if (msg.callback != null) { 6 handleCallback(msg); 7 } else { 8 if (mCallback != null) { 9 if (mCallback.handleMessage(msg)) { 10 return; 11 } 12 } 13 handleMessage(msg); 14 } 15 }
從方法名稱來看,這個方法是用來分發消息的,咱們進入方法裏面看一下,首先先判斷Message的callback是否爲空,這個callback究竟是個啥?跟進去看一下
/*package*/ Runnable callback;
是個Runnable,這裏就是咱們在getPostMessage這個方法中提到的把Runnable對象傳遞給Message的callback變量,也就是說,若是咱們調用Hander的postXX的方法,那麼就會把這個Runnable對象賦值給Message的callback變量,那麼在上述代碼的第五行中,當這個變量不爲空的時候,就會調用handleCallback(msg):這個方法去處理消息,
private static void handleCallback(Message message) { message.callback.run(); }
看到這裏,你們就明白了,咱們調用Handler 的postXX方法時,能夠在這個Runnalble對象的run方法裏去執行UI操做了。
接着分析上面代碼的else分支,
1 else { 2 if (mCallback != null) { 3 if (mCallback.handleMessage(msg)) { 4 return; 5 } 6 } 7 handleMessage(msg); 8 }
若是Handler的mCallback成員變量若是不爲空,那麼就調用這個接口的handleMessage方法,不然的話,就走handleMessage(msg)方法,
/** * Subclasses must implement this to receive messages. */ public void handleMessage(Message msg) { }
好了,這下終於到咱們比較熟悉的Handler的處理消息方法上去了,這個方法就是咱們在Handler裏處理UI操做的方法了。
本篇只是單獨地對Handler這個類分析它的內部實現及對外提供的接口及方法,並無對與Handler緊密相關聯的Looer類,MessageQueue類,Message進行分析,目的是爲了清晰地對單個封閉的類進行感性的認識以後,再對與之關聯的類相互之間的關聯調用進行分析;
總結:
1,Handler能夠處理 Message及Runnable對象;
2,Handler提供多種構造方法,從而獲得與之緊密關聯的Looper對象,MessageQueue對象等;
3,Handler提供了兩種類型的發送消息的方法,post版本及sendMessage版本
4,Handler提供了重要的dispatchMessage方法,在這個方法中明確是把消息給Runnable對象的run方法仍是給Handler子類的handlMessage方法執行UI操做。