一. 圖解與概述html
首先Android中 的每個線程都會對應一個MessageQueue和Looper。見名知意,MessageQueue即線程用來維護線程產生的消息的消息隊列,而這個 隊列的調度則是由Looper來完成的。Looper負責將產生的消息放入隊列,並及時的將合適的消息從隊列中取出並交由合適的接受者處理。處理消息的便 是每一個線程內部的Handler對象,特別是在UI線程中,因爲Handler與UI處於同一個線程,因此咱們就能夠經過Handler處理接收到的消息 並及時更新UI中的組件。java
上述描述便可以實如今其它線程中完成耗時操做並在UI線程中經過Handler更新組件以反映耗時操做的處理效果。android
如下是它們之 間關係的圖示:程序員
理解概念:設計模式
Message:消息,其中包含了消息ID,消息處理對象以及處理的數據等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,須要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。
MessageQueue:消息隊列,用來存放Handler發送過來的消息,並按照FIFO規則執行。固然,存放Message並不是實際意義的保存,而是將Message以鏈表的方式串聯起來的,等待Looper的抽取。
Looper:消息泵,不斷地從MessageQueue中抽取Message執行。所以,一個MessageQueue須要一個Looper。
Thread:線程,負責調度整個消息循環,即消息循環的執行場所。
安全
簡單關係:多線程
Handler,Looper和MessageQueue就是簡單的三角關係。框架
Looper和MessageQueue一一對應,線程和looper也是一一對應,建立一個Looper的 同時,會建立一個MessageQueue。異步
而Handler與它們的關係,只是簡單的彙集關係,即Handler裏會引用當前線程裏的特定Looper 和MessageQueue。
這樣說來,多個Handler均可以共享同一Looper和MessageQueue了。ide
固然,這些Handler也就運行在同一個線程裏。
消息循環過程:
生成消息
1 Message message = handler.obtainMessage(); 2 message.arg1 = id; 3 message.obj = drawable; 4 handler.sendMessage(message);
發送消息
1 /** 2 * <b>The time-base is {@link android.os.SystemClock#uptimeMillis}.</b> 3 * to this handler. 4 * @param uptimeMillis The absolute time at which the message should be 5 * {@link android.os.SystemClock#uptimeMillis} time-base. 6 * @return Returns true if the message was successfully placed in to the 7 * looper processing the message queue is exiting. Note that a 8 * the looper is quit before the delivery time of the message 9 */
public boolean sendMessageAtTime(Message msg, uptimeMillis) 10 { 11 sent = ; 12 MessageQueue queue = mQueue; 13 (queue != ) { 14 msg.target = ; 15 sent = queue.enqueueMessage(msg, uptimeMillis); 16 } 17 { 18 RuntimeException e = RuntimeException( 19 + , e.getMessage(), e); 20 } 21 sent; 22 }
在 Handler.java的sendMessageAtTime(Message msg, long uptimeMillis)方法中,咱們看到,它找到它所引用的MessageQueue,而後將Message的target設定成本身(目的是爲了在 處理消息環節,Message能找到正確的Handler),再將這個Message歸入到消息隊列中。
Looper從消息隊列中抽取消息
1 public static final void loop() { 2 Looper me = myLooper(); 3 MessageQueue queue = me.mQueue; 4 () { 5 Message msg = queue.next(); 6
7
8
9 (msg != ) { 10 (msg.target == ) { 11
12 ; 13 } 14 (me.mLogging!= ) me.mLogging.println( 15 ); 16 msg.target.dispatchMessage(msg); 17 (me.mLogging!= ) me.mLogging.println( 18 + msg.callback); 19 msg.recycle(); 20 } 21 } 22 }
在Looper.Java的loop()函數裏,咱們看到,這裏有一個死循環,不斷地從MessageQueue中獲取下一個(next方法)Message,而後經過Message中攜帶的target信息,交由正確的Handler處理(dispatchMessage方法)。
處理
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 }
在 Handler.java的dispatchMessage(Message msg)方法裏,其中的一個分支就是調用handleMessage方法來處理這條Message,而這也正是咱們在職責處描述使用Handler時須要 實現handleMessage(Message msg)的緣由。
至於dispatchMessage方法中的另一個分支,我將會在後面的內容中說明.
至此,咱們看到,一個Message經由Handler的發送,MessageQueue的入隊,Looper的抽取,又再一次地回到Handler的懷抱。而繞的這一圈,也正好幫助咱們將同步操做變成了異步操做。
Handler所處的線程及更新UI的方式
在 主線程(UI線程)裏,若是建立Handler時不傳入Looper對象,那麼將直接使用主線程(UI線程)的Looper對象(系統已經幫咱們建立 了);在其它線程裏,若是建立Handler時不傳入Looper對象,那麼,這個Handler將不能接收處理消息。在這種狀況下,通用的做法是:
1 class LooperThread extends Thread { 2 public Handler mHandler; 3 public void run() { 4 Looper.prepare(); 5 mHandler = new Handler() { 6 public void handleMessage(Message msg) { 7 // process incoming messages here
8 } 9 }; 10 Looper.loop(); 11 } 12 }
在建立Handler以前,爲該線程準備好一個Looper(Looper.prepare),而後讓這個Looper跑起來(Looper.loop),抽取Message,這樣,Handler才能正常工做。
所以,Handler處理消息老是在建立Handler的線程裏運行。而咱們的消息處理中,不乏更新UI的操做,不正確的線程直接更新UI將引起異常。所以,須要時刻關心Handler在哪一個線程裏建立的。
Message中文是消息,及線程處理的最小單元,裏面帶有處理的數據集,或還帶有操做,及告訴目的地要作什麼事情, 每一個MessageQueue裏包含有Message。每一個Message不是直接插入到MessageQueue裏的,而是經過MessageQueue.IdleHandler 與looper一塊兒工做,把Message放到MessageQueue裏,及addIdleHandler(MessageQueue.IdleHandler handler) 和removeIdleHandler(MessageQueue.IdleHandler handler) 方法,把MessageQueue.IdleHandler壓入到MessageQueu裏。
2,Thread和HandlerThread的關係
HandlerThread就是帶有Looper循環的Thread.
3,Looper介紹
Looper即一個循環,必須綁定到一個固定的線程裏,經過getThread()方法能夠得到該looper綁定的Thread對象,經過 getMainLooper()得到主線程裏的looper對象,myLooper()能夠得到當前線程裏的looper對象,經過myQueue()方 法能夠得到當前線程裏的messageQueue對象。
4,Thread、HandlerThread、和Looper的關係的關係
通常聲明一個thread是沒有帶looper循環的,可是能夠經過Looper.prepare()方法給一個線程加上 looper;Looper.loop()執行該looper綁定的線程裏的messageQueue,直到該loopger結 束;Loop.quit()結束該循環,實例代碼以下:
1 class LooperThread extends Thread { 2 public Handler mHandler; 3
4 public void run() { 5 Looper.prepare(); 6
7 mHandler = new Handler() { 8 public void handleMessage(Message msg) { 9 // process incoming messages here
10 } 11 }; 12
13 Looper.loop(); 14 } 15 }
5,Handler和Thread HandlerThread Looper Message MessageQueue的關係
它把消息發送到該生成它的線程裏的MessageQueue裏,而後當Message出隊列的時候,就執行該消息。
post(Runnable), , ,是用來處理runnable對象的;postAtTime(Runnable, long)postDelayed(Runnable, long)
sendEmptyMessage(int), , , and sendMessage(Message)sendMessageAtTime(Message, long)sendMessageDelayed(Message, long)方法是
能夠經過handleMessage (Message msg) 方法來接收消息。
實例化:Handler(Looper looper)
二. 多線程與異步
當程序啓動的時候android會自動建立一個進程和一個線程,這個線程負責界面更新,收集系統事件和用戶的操做事件等並分配給對應的組件,因此這個線程很是重要 被稱爲主線程,由於所的和UI有關的操做都是在這個線程當中進行的因此也被稱做UI線程。因此說默認狀況下主線程和UI線程指的是同一個線程。
Android的UI系統參考了不少SWT的設計模式。好比,UI線程機制,底層JNI實現 etc.
Android 的UI系統是非線程安全的,意思是說只有建立UI的線程(也就是主線程)才能夠對UI進程操做。若是咱們在其它線程中執行了一些操做,而這些操做的結果又須要經過UI展示給用戶,必需把這更新UI的操做轉移到到UI線程中執行。
不少Java起步的程序員對UI線程中的"消息循環"會感受陌生。其實就是在線程內部有一個死循環一直監聽系統事件(用戶的操做等)並把任務分發給對應的 組件(有興趣的能夠看看NDK附帶的native-activity的一個sample,在c中的實現方式就是一個while(1)的死循環)。主線程通 過Looper實現了消息的循環處理。
若是一個線程裏邊有一個死循環,那麼這個循環就會一直在死循環裏邊循環,而且這個線程不會過多的cpu資源,那麼這個線程確定的阻塞的。若是線程只是一直 循環沒有什麼意義,實際狀況一般須要線程根據不一樣的條件運行不一樣的方法。咱們一般的做法可能會加一個switch開關,根據條件的不一樣去調用不一樣的方法。
線程間通訊(最多見的就是,worker線程須要更新UI),這個時候實際是包含兩個內容:一,數據的傳遞;二,方法的傳遞; Android中的Message用於數據傳遞,而Handler就是方法傳遞(實際上是方法的執行者,Handler會把這個方法放到Handler所在 的線程當中去執行);MessageQueue是Message的容器和Java中的Queue同樣都是容器,只不過Message Queue是專門用於裝載Message的容器。Looper則是一個線程中的死循環用於管理MessageQueue,它負責阻塞讀取 MessageQueue中的信息(若是MessageQueue中沒有信息會一直在那裏),挨個讀取並把這個Message分發給對應的Handler 去執行。
首先看一下mHandler.obtainMessage(SHOW_ALERT, Greetings).sendToTarget();會執行什麼。
經過查看Handler的源碼發現執行了下邊的代碼。
1 public final Message obtainMessage(int what, Object obj){ 2 return Message.obtain(this, what, obj); 3 }
1 public static Message obtain(Handler h, int what, Object obj) { 2 Message m = obtain(); 3 m.target = h; 4 m.what = what; 5 m.obj = obj; 6 return m; 7 } 8 /**
9 * Return a new Message instance from the global pool. Allows us to 10 * avoid allocating new objects in many cases. 11 */
12 public static Message obtain() { 13 synchronized (mPoolSync) { 14 if (mPool != null) { 15 Message m = mPool; 16 mPool = m.next; 17 m.next = null; 18 return m; 19 } 20 } 21 return new Message(); 22 }
看到這裏咱們應該明白爲何Google建議咱們使用obtainMessage而不是new一個Message.這也是符合了Android中的對象回收機制。
1 public void sendToTarget() { 2
3 target.sendMessage(this);//targe就是一個Handler
4
5 } 6 sendMessage()會調用下面的sendMessageAtTime()把Message加入MessagQueue; 7
8 public boolean sendMessageAtTime(Message msg, long uptimeMillis){ 9 boolean sent = false; 10 MessageQueue queue = mQueue; 11 if (queue != null) { 12 msg.target = this; 13 sent = queue.enqueueMessage(msg, uptimeMillis); 14 }else { 15 RuntimeException e = new RuntimeException( 16 this + " sendMessageAtTime() called with no mQueue"); 17 Log.w("Looper", e.getMessage(), e); 18 } 19 return sent; 20 }
到此咱們的Message對象被加入到了Handler所在線程(也就是主線程)中的MessageQueue這個存儲和管理Message的容器當中。下一步就該由Looper接手一個一個的取出Message對象處理了。Looper最主要的方法就是loop()方法
1 public static final void loop() { 2 Looper me = myLooper(); 3 MessageQueue queue = me.mQueue; 4 while (true) {//死循環
5 Message msg = queue.next(); // might block
6 if (msg != null) { 7 if (msg.target == null) {//退出死循環的機制 8 // No target is a magic identifier for the quit message.
9 return; 10 } 11 if (me.mLogging!= null) me.mLogging.println( 12 ">>>>> Dispatching to " + msg.target + " "
13 + msg.callback + ": " + msg.what 14 ); 15 msg.target.dispatchMessage(msg);//target of a msg is a Handler
16 if (me.mLogging!= null) me.mLogging.println( 17 " Finished to " + msg.target + " "
18 + msg.callback);//msg.callback is a Runnable
19 msg.recycle(); 20 } 21 } 22 }
Looper會一直阻塞讀取MessagQueue中的Message對象(Message msg = queue.next()),當讀取到一個Message時就會調用msg.target.dispatchMessage(msg)把這個 Message分發給對應的Handler去處理,等Handler把任務處理完了再接着讀取下一個Message對象並處理。
1 /**
2 * Handle system messages here. 3 */
4 public void dispatchMessage(Message msg) { 5 if (msg.callback != null) { 6 handleCallback(msg);// call the run method of the runnable object I guess
7 } else { 8 if (mCallback != null) { 9 if (mCallback.handleMessage(msg)) { 10 return; 11 } 12 } 13 handleMessage(msg); 14 } 15 }
最後回來了咱們的handlerMessage(msg);這個方法中。若是是用的不是sendMessage是是Hadler.post(Runnable)會調用
1 private final void handleCallback(Message message) { 2 message.callback.run(); 3 }
這就是爲何在Handler中post的Runnable不會開啓一個新的線程的緣由。通過上面的追蹤咱們應該能明白不是全部 的線程均可以有Handler去執行handlerMessage或者處理Runnalbe的。其必要條件就是這個線程要有一個一直循環的 Looper.Looper一直循環確定要有一個方法能夠退出循環。
當咱們調用msg.sendToTarget()的時候,咱們的msg對象應付被壓入MessageQueue的尾部。Looper在 MessageQueue的另外一端一個一個的讀取信息並處理。根據msg的target屬性把cpu分配給對應的Handler去執行任務,這時 Handler會根據msg中的屬性調用msg.handleMsg()或者msg.callback.run();當一個msg中的消息處理完返回以後 Looper會把這個msg放入msgPool當中方便下次再重複利用。從而減小對象的建立。Looper再從MessageQueue中讀取下一個信 息,如此反覆。。
理解了這些其實就不難想象ANR是如何實現的了。當用戶執行操做(好比點擊了一個按鈕)系統會生成一個Message對象,把用戶操做的信息寫入 Message對象,並把這個Message對象壓入MessageQueue隊列的尾部。系統過一段時間(通常是五秒)後會再來檢查,剛剛放入的信息是 不是已經被處理了,若是信息還在隊列中就代表。處理前面信息的過程中發生的阻塞,用戶的操做沒有及時獲得響應。系統彈出ANR對話框。
做個總結:
由於UI線程須要保持一直運行的狀態,因此要有一個循環保持這個線程不會死掉,但這個線程又必需阻塞,以減小cpu的消耗。android中的這個循 環就是經過Looper實現的。有了這個 Looper,Looper就佔據了整個線程,致使全部的方法想在些線程中運行就必需經過這個Looper,因此要有個方法能夠進入這個Looper的內 部。MessageQueue就擔當了這個通道 的角色。Message擔當了集合的角色。全部在UI線程中運行的方法都必需經過MessageQueue進入Looper內部,無論 是用戶定義的方法仍是系統事件包括onCreate(),onStop(),用戶點擊事件etc..
消息系統的基本原理和構成
從通常的消息系統模型的創建大體構成如下幾個部分:
l 消息原型
l 消息隊列
l 發送消息
l 消息循環
l 消息獲取
l 消息派發
l 消息處理
大體模型圖以下:
消息系統模型通常會包括以上七個部分(消息原型,消息隊列,消息發送,消息循環,消息獲取,消息派發,消息處理)。實際上的核心是消息隊列和消息循環,其他部分都是圍繞這兩部分進行的。
從前面文檔的分析中咱們知道Handler就是用來創建消息處理的系統模型,那麼和這裏基本消息系統模型相比,那麼Handler又是如何囊括這七個部分的呢?
在Android中對這六個部分進行了抽象成四個獨立的部分:
Handler,Message,MessageQueue,Looper;
Handler可以實現消息系統模型,那麼具體是如何進行工做的呢,下面探究一下這其中工做的方法和原理。
四. Handler工做原理分析
要了解Handler工做原理,先看一下這個系統模型具體組成的層次結構框架是個什麼樣的。
實現Thread的消息循環和消息派發,缺省狀況下Thread是沒有這個消息循環的既沒有Looper;須要主動去建立,而後啓動Looper的消息循環loop;與外部的交互經過Handler進行;消息隊列,由Looper所持有,可是消息的添加是經過Handler進行;
消息循環和消息隊列都是屬於Thread,而Handler自己並不具備Looper和MessageQueue;可是消息系統的創建和交互,是Thread將Looper和MessageQueue交給某個Handler維護創建消息系統模型。因此消息系統模型的核心就是Looper。消息循環和消息隊列都是由Looper創建的,
而創建Handler的關鍵就是這個Looper。
一個Thread同時能夠對應多個Handler,一個Handler同時只能屬於一個Thread。Handler屬於哪一個Thread取決於Handler在那個Thread中創建。
在一個Thread中Looper也是惟一的,一個Thread對應一個Looper,創建Handler的Looper來自哪一個Thread,Handler屬於哪一個Thread。
故創建Thread消息系統,就是將Thread的Looper交給Handler去打理,實現消息系統模型,完成消息的異步處理。
Handler與Thread及Looper的關係能夠用下面圖來表示:
Handler並不等於Thread,必須經過Thread的Looper及其MessageQueue,用來實現Thread消息系統模型,依附於Thread上。
在線程創建Handler時:
使Handler知足消息系統須要的條件,將Thread中的Looper和MessageQueue交給Handler來負責維護。
在線程中創建Handler,須要作如下工做:
l 獲取Thread中的Looper交給Handler的成員變量引用維護;
l 經過Looper獲取MessageQueue交給Handler的成員變量引用維護。
那麼消息系統模型創建完成以後,按照消息系統運行,從Handler來看就是發送消息派發消息,與此線程消息系統的交互都由Handler完成。
消息發送和派發接口:
l post(runnable)消息,Runnable是消息回調,通過消息循環引起消息回調函數執行;
l sendMessage(Message)消息,通過消息循環派發消息處理函數中處理消息;
l dispatchMessage 派發消息,如果post或帶有回調函數則執行回調函數,不然執行
消息處理函數Handler的handleMessage(一般派生類重寫)。
以上就是Handler如何實現Thread消息系統模型的大體介紹, 下面將具體分析是如何實現消息系統模型運行的。
五. Handler實現流程分析
咱們知道Handler就是一個消息系統的外殼,屬於某個Thread幷包裝了Thread的Looper及其MessageQueue;與外部進行交互(同一個線程內或者線程之間),接收派發和處理消息,消息系統模型的核心是Looper。下面看看Handler是如何創建跑起來的,以msg消息爲例,runnable實質是同樣。
Handler惟一屬於某個Thread,在某個Thread中創建Handler時,須要獲取Thread的Looper及其MessageQueue,創建Handler關鍵是Looper的來源。
Handler提供了好幾個構造函數但其本質一致:
由外部傳入Looper:當前線程或其餘線程
public Handler(Looper looper) { //初始化構建消息系統參數 mLooper = looper; mQueue = looper.mQueue; mCallback = null; }
從當前線程獲取:由建立Handler的Thread決定
public Handler() { //初始化構建消息系統參數 mLooper = Looper.myLooper(); mQueue = mLooper.mQueue; mCallback = null; } public static Looper myLooper() { return sThreadLocal.get(); }
無論哪一種方式,咱們知道Thread在默認狀況下是沒有創建消息循環Looper實例的。
要實現消息循環必須確保Thread的Looper創建。如何確保呢?
Looper提供了靜態函數:
public static void prepare() { if (sThreadLocal.get() != null) { throw new RuntimeException("Only one Looper may be created per thread"); } sThreadLocal.set(new Looper()); } //存儲線程的局部變量 static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
每個線程調用Looper.prepare時,都會建立爲其惟一的Looper。
要創建Handler,須要先建立線程的Looper,才能創建消息系統模型。經過Looper咱們創建了
Thread上的消息系統模型Handler,能夠來進行消息系統的一系列流程了。
消息發送兩種方式:post和sendMessage;
post:針對runnable對象;Runnable是一個接口,就是一個回調函數(提供了run方法)
sendMessage:針對Message對象;
下面經過代碼具體看一下這個過程:
public final boolean post(Runnable r){ return sendMessageDelayed(getPostMessage(r), 0); } public final boolean sendMessage(Message msg){ return sendMessageDelayed(msg, 0); }
看到post和sendMessage發送消息時,僅僅是對象不一樣而已,Runnable和Message;
但實際上都是Message的形式來描述。
這跟我一般理解的消息機制不一樣:
一般post消息是將消息加入到消息隊列中並不當即執行就返回,send消息是當即執行等待消息執行完才返回。
而這裏post或者send都是將消息放入到消息隊列中,而後當即返回,等待消息循環時獲取消息被執行。
這裏提供了衆多的消息發送方法來指定消息的執行時間和順序,具體能夠查看源代碼。
消息執行順序是根據消息隊列中消息的排列順序而定。
下面看一下發送消息後將消息加入到消息隊列中的代碼:
由Handler調用MessageQueue的enqueueMessage方法:
1 final boolean enqueueMessage(Message msg, long when) { 2
3 Message p = mMessages; 4
5 if (p == null || when == 0 || when < p.when) { 6 msg.next = p; 7 mMessages = msg; 8 } 9 else { 10
11 Message prev = null; 12 while (p != null && p.when <= when) { 13 prev = p; 14 p = p.next; 15 } 16
17 msg.next = prev.next; 18 prev.next = msg; 19 } 20 …… 21 }
能夠看到是按照時間順序將消息加入到MessageQueue中;
如今將消息加入到消息隊列中存儲起來,消息並未獲得處理,下一步必然是如何派發消息和處理消息。
創建Thread消息循環由Looper完成,存在一個消息調度死循環:
public static void loop() { MessageQueue queue = me.mQueue; while (true) { Message msg = queue.next(); // might block if (msg != null) { if (msg.target == null) { // No target is a magic identifier for the quit message. return; } //派發消息 到target(Handler) msg.target.dispatchMessage(msg); //回收Msg到msgPool msg.recycle(); } } }
這裏看到消息派發是由Message的target完成,這個target是什麼呢?是一個Handler。
消息系統是經過Handler用來與外部交互,把消息派發出去。能夠看到沒有這個Handler,消息循環將結束。
消息派發由Looper經過Handler完成:
public void dispatchMessage(Message msg) { //首先判斷runnable對象 if (msg.callback != null) { handleCallback(msg); } else { //整個消息系統的回調函數 能夠不用實現本身Handler if (mCallback != null) { if (mCallback.handleMessage(msg)) { return; } } //消息處理 一般交給Handler派生類 handleMessage(msg); } }
經過消息派發,這樣就實現消息的異步處理。
前面看到消息發送有兩種方式:
post(Runnable對象),sendMessage(Message對象),而中間都是經過Message對象保存在MessageQueue中。而後消息派發時處理方式不一樣。若是在sendMessage時將將消息對象附上Runnable對象,則post和sendMessage沒有區別了。因此這兩種方式很好理解基本一致,處理的方式不一樣罷了。
消息系統模型中,咱們的真正的消息原型是什麼,都具備那些功能,下面看一下Message中到底包含了那些東西,能有效幫助咱們合理的運用消息系統來完成一些任務和處理。
Message消息原型:
public final class Message implements Parcelable { //標識消息 public int what; int flags; long when; //傳遞簡單數據 public int arg1; public int arg2; //傳遞較複雜數據 對象 public Object obj; Bundle data; //處理消息的目標Handler Handler target; //消息派發時 執行的Runnable對象 Runnable callback; //使消息造成鏈表 Message next; //創建一個消息pool,回收msg,以免重複建立節約開銷 private static Message sPool; private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 10; }
看到提供了很豐富的屬性來描述消息,針對具體問題選擇使用那些屬性去怎麼樣描述消息了。
獲取新的Message對象時,Message提供了obtain方法:避免咱們本身去分配Message新的對象,經過obtain獲取,可能從MessagePool中獲取,節約開銷。
下面看一下這個MessagePool是如何創建的:
一般消息處理完畢的時候,消息也基本上處於無用狀態能夠釋放回收了。對於須要頻繁的建立釋放的對象來講,建立和釋放類實例都是要開銷的,太頻繁的使開銷增大很差,像Message這種頗有可能會頻繁的建立。
因而咱們能夠將建立的對象用完以後保存在一個Pool裏面,以便再重複利用節約頻繁建立釋放開銷。是如何創建的呢?必然是在消息處理完畢以後才能進行。
MessagePool創建:
public static void loop() { while (true) { //派發消息 msg.target.dispatchMessage(msg); //消息處理完畢 回收 msg.recycle(); } } public void recycle() { //回收Message 創建全局的MessagePool if (sPoolSize < MAX_POOL_SIZE) { next = sPool; sPool = this; sPoolSize++; } }
以上這就是整個Handler做用及消息系統模型的創建。
使用也很是簡單,雖然有不少方式,但只要理解Handler是創建在Looper上,實現Thread的
消息系統處理模型,實現消息異步處理,我想對與Handler基本應用上沒有什麼不能理解的了。
其餘方面能夠去看源碼了。
Handler使用起來是很是簡單的,關鍵就是如何利用消息的異步處理,來合理的完成咱們
須要功能和任務。對於一個Thread,咱們使用好幾個Handler來進行異步處理,也能夠建立新的Thread,
經過Handler來實現消息異步處理等等,應用場景不少如何用的好用的合理,這就沒什麼經驗了。
至於如何使用,源碼中不少例子能夠看一下AsyncQueryHandler這個類,其中兩個線程,
完成查詢工做,經過Handler進行線程之間有消息傳遞。感受這個利用的很好很巧妙。