Handler是我們在開發中接觸到最多的類了。
他可謂是Android消息機制中的總調度員。他幾乎無所不能:創建消息可以是他,發消息是他,處理消息是他,移除消息還是他。所以,很多開發者對Handler很熟悉,對其背後底層默默工作的MessageQueue和Looper反而比較陌生。
我們先看一下Handler的類結構:
從圖中我們可以看出,其包含了文章開頭所講的所有功能函數。
Handler的主要功能有:
Handler的構造函數最終目的就是設置Handler中的幾個重要的成員變量:mLooper
,mQueue
,mCallback
,mAsynchronous
。
filed | 含義 | 說明 |
---|---|---|
mLooper | 消息循環器Looper | 該Handler所對應的Looper |
mQueue | 消息隊列MessageQueue | 該Handler所處理消息所在的消息隊列 |
mCallback | Handler級別回調 | Handler處理所有send Message系列消息時的統一回調。(下文會細述) |
mAsynchronous | 是不是異步處理方式 | 其實只有一個作用,就是在設置Barrier時仍可以不受Barrier的影響被正常處理,如果沒有設置 Barrier,異步消息就與同步消息沒有區別 |
代碼如下:
public Handler(Callback callback, boolean async) {
//這個會判斷一個警告,意思是說Handler class應該是一個靜態類,否則可能導致內存洩漏,
// 至於為什麼可以參考鏈接http://stackoverflow.com/questions/11407943/this-handler-class-should-be-static-or-leaks-might-occur-incominghandler
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());
}
}
//必須先執行Looper.prepare(),才能獲取Looper對象,否則為null.
mLooper = Looper.myLooper();
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread that has not called Looper.prepare()");
}
mQueue = mLooper.mQueue;//消息隊列,來自Looper對象
mCallback = callback;//回調方法
mAsynchronous = async; //設置消息是否為異步處理方式
}
代碼比較簡單,過程為:
mLooper
,如果mLooper為空,說明當前線程並不是一個可接受消息的線程,需要在線程開啟時用Looper.prepare()和Looper.loop()來初始化才可以繼續。Handler也是在這裡和Looper、MessageQueue聯繫起來的。
Handler中通過一系列的obtainMessage()方法,封裝了Message從消息池中取到符合要求的消息的方法。
public final Message obtainMessage()
public final Message obtainMessage(int what)
public final Message obtainMessage(int what, Object obj)
public final Message obtainMessage(int what, int arg1, int arg2)
public final Message obtainMessage(int what, int arg1, int arg2, Object obj)
這些方法都會將該Handler設置為該消息的
target
。
Handler發送消息主要有兩種方法:post系列方法和send系列方法。
post runnable 系列
final boolean post(Runnable r)
final boolean postAtTime(Runnable r, long uptimeMillis)
final boolean postAtTime(Runnable r, Object token, long uptimeMillis)
final boolean postDelayed(Runnable r, long delayMillis)
final boolean postAtFrontOfQueue(Runnable r)
send Message 系列
final boolean sendEmptyMessage(int what)
final boolean sendEmptyMessageDelayed(int what, long delayMillis)
final boolean sendEmptyMessageAtTime(int what, long uptimeMillis)
final boolean sendMessageDelayed(Message msg, long delayMillis)
boolean sendMessageAtTime(Message msg, long uptimeMillis)
final boolean sendMessageAtFrontOfQueue(Message msg)
他們之間的調用關係如圖:
他們最終都是將某個消息壓入到MessageQueue中,等待處理。區別在於:
Activity.runOnUiThread(Runnable)
View.post(Runnable)
View.postDelayed(Runnable, long)
這也是post系列方法存在的意義。從上一篇文章中我們可以知道,Looper循環過程中,取出一條消息後,是通過調用該消息對應的Handler的dispatchMessage(Message msg)對消息進行處理。
code in Looper.loop():
msg.target.dispatchMessage(msg); //msg.target就是與此線程關聯的Handler對象,調用它的dispatchMessage處理消息
Handler處理消息的源碼如下:
/**
* 在這裡處理系統消息
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {//post系列方法走這裡
handleCallback(msg);
} else {//sendMessage系列方法走這裡
if (mCallback != null) {//Handler構造函數中定義了Callback的這裡處理
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
其處理邏輯流程如圖:
其實邏輯很簡單。
1.
中的情況,看該Handler在被創建時,是否有設定Handler級別的Callback,如果有,處理之。這裡和1.
中所描述情況的區別是,Handler級別的Callback是有返回值的,處理完後會根據返回值看是否需要進一步處理。handleMessage(Message msg)
中做最後處理。大多數情況下的消息都在這裡處理。根據Handler中的發送消息的方法源碼可知,Post系列方法的都會調用getPostMessage(Runnable r)函數將一個Runnable對象封裝成一條Message,封裝時,會將該runnable參數作為消息的callback。所以,我們可以得出結論:
post runnable系列方法消息的最終都在handleCallback(msg)中處理。
根據消息入列的區別,移除消息也分為removeMessages
和removeCallbacks
兩系列。和發送消息類似,
Handler的移除消息最終還是對其對應的MessageQueue的操作,從中移除符合條件的消息。
使用Handler的過程中,為避免Activity調用onDestroy後,Handler的MessageQueue中仍存在Message,一般會在onDestroy中調用removeCallbacksAndMessages()方法。
mLooper
,mQueue
,mCallback
,mAsynchronous
。首先設置好mLooper,mLooper中有一個和其一一對應的變量:mQueue。 </div>