MessageQueue:消息隊列,使用FIFO規則執行,每個線程只能夠擁有一個MessageQueue,在建立Looper對象會建立一個html
MessageQueue用來容納Message隊列的,其中的Message是由Looper來分發的,Message不能直接添加到MessageQueue中,而是要經過與Looper關聯的Handler去添加。java
建立一個線程的時候,並不會自動建立其MessageQueue。一般使用一個Looper對象對該線程的MessageQueue進行管理。主線程建立時,會建立一
個默認的Looper對象,而Looper對象的建立,將自動建立一個Message Queue。其餘非主線程,不會自動建立Looper,要須要的時候,經過調
用prepare函數來實現。
Message消息對象:MessageQueue中存放的對象,一個MEssageQueue中能夠包含多個MEssage,能夠經過Message.obtain()或者Handle.obtainMessage()獲取Message對象,可是這並不必定是直接建立一個新的實例,而是先從消息池中看有沒有可用的Message實例,存在則直接取出返回這個實例,若是消息池中沒有可用的MEssage實例i,則採用給定的參數建立一個Message對象,調用removeMessage()時,將Message從MessageQueue中刪除,同時放入到消息池中。android
Message是線程之間傳遞信息的載體,包含了對消息的描述和任意的數據對象。Message中包含了兩個額外的 int字段和一個object字段,這樣在大部分狀況下,使用者就不須要再作內存分配工做了。雖然Message的構造函數是public的,可是最好是使用Message.obtain( )或Handler.obtainMessage( )函數來獲取Message對象,由於Message的實現中包含了回收再利用的機制,能夠提供效率。 app
B、建立消息ide
1 |
public final Message obtainMessage() |
3 |
public final Message obtainMessage( int what) |
5 |
public final Message obtainMessage( int what, Object obj) |
7 |
public final Message obtainMessage( int what, int arg1, int arg2) |
9 |
public final Message obtainMessage( int what, int arg1, int arg2, Object obj) |
obtainmessage()是從消息池中拿來一個msg 不須要另開闢空間new函數
new須要從新申請,效率低,obtianmessage能夠循環利用;工具
- //use Handler.obtainMessage(),instead of msg = new Message();
- //because if there is already an Message object,that not be used by
- //any one ,the system will hand use that object,so you don't have to
- //create and object and allocate memory.
- //it is also another example of object recycling and reusing in android.
- Message msg = mHandler.obtainMessage();
- msg.what = UPDATE_LISTVIEW;
- msg.obj = current + "/" + total + "songs";
- //this method is called from worker Thread,so we cannot update UI from here.
- msg.sendToTarget();
在看下面代碼:
- Message msg = handler.obtainMessage();
- msg.arg1 = i;
- msg.sendToTarget();
-
-
- Message msg=new Message();
- msg.arg1=i;
- handler.sendMessage(msg);
第一種寫法是message 從handler 類獲取,從而能夠直接向該handler 對象發送消息,第二種寫法是直接調用 handler 的發送消息方法發送消息。
C、刪除消息
刪除在消息隊列中未處理的消息oop
1 |
public final void removeMessages( int what) |
3 |
public final void removeMessages( int what, Object object) |
D、發送消息post
1 |
public final boolean sendMessage(Message msg) |
3 |
public final boolean sendMessageDelayed(Message msg, long delayMillis) |
5 |
public final boolean post(Runnable r) |
7 |
public final boolean postDelayed(Runnable r, long delayMillis) |
三、Looperui
frameworks\base\core\java\android\Os\Looper.java
Looper是線程用來運行消息循環的。線程自己是沒有消息循環的,須要在線程中調用perpare函數,而後調用loop去處理消息。在Android中,系統在啓動主線程的時候會自動爲之創建一個Looper。
Android中的Looper類,是用來封裝消息循環和消息隊列的一個類,用於在android線程中進行消息處理。handler其實能夠看作是一個工具類,用來向消息隊列中插入消息的。
創建本線程的Looper:
public static final void prepare()
運行本線程的Looper:
public static final void loop()
注意:寫在Looper.loop()以後的代碼不會被執行,這個函數內部應該是一個循環,當調用mHandler.getLooper().quit()後,loop纔會停止,其後的代碼才能得以運行。
獲取本線程的Looper:
public static final Looper myLooper()
相似的 Looper.getMainLooper() 用於獲取主線程的Looper對象。
獲取主線程的Looper:
public synchronized static final Looper getMainLooper()
四、Handler
frameworks\base\core\java\android\Os\Handler.java
Handler是用來發送和處理與線程相關聯的Message和Runnable對象的。每一個Handler都與一個單獨的線程以及線程消息隊列相關聯的。當你建立Handler時,Handler就與線程以及線程消息隊列綁定了,從那之後,Handler就能夠將 Message和Runnable發送給對應的消息隊列,而且可以處理從消息隊列中出來的消息。
一般是經過Handler對象來與Looper進行交互的。Handler可看作是Looper的一個接口,用來向指定的Looper發送消息及定義處理方法。
默認狀況下Handler會與其被定義時所在線程的Looper綁定,好比,Handler在主線程中定義,那麼它是與主線程的Looper綁定。
mainHandler = new Handler() 等價於new Handler(Looper.myLooper()).(這裏Looper.myLooper()獲取本線程的Looper:相似的 Looper.getMainLooper() 用於獲取主線程的Looper對象。)
在非主線程中直接new Handler() 會報以下的錯誤:
E/AndroidRuntime( 6173): Uncaught handler: thread Thread-8 exiting due to uncaught exception
E/AndroidRuntime( 6173): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
緣由是非主線程中默認沒有建立Looper對象,須要先調用Looper.prepare()啓用Looper。
A、建立Handler:
建立與本地線程相關聯的Handler:
3 |
public Handler(Callback callback) |
建立與指定線程相關聯的Handler:
1 |
public Handler(Looper looper) |
3 |
public Handler(Looper looper, Callback callback) |
E、處理消息
在Looper的loop函數中循環取出MessageQueue的接收消息隊列中的消息,而後調用Hander的dispatchMessage函數對消息進行處理,至於如何處理(相應消息)則由用戶指定(三個方法,優先級從高到低:Message裏面的Callback,一個實現了Runnable接口的對象,其中run函數作處理工做;Handler裏面的mCallback指向的一個實現了Callback接口的對象,裏面的handleMessage進行處理;處理消息 Handler對象對應的類繼承並實現了其中handleMessage函數,經過這個實現的handleMessage函數處理消息)。
(5) 基於以上知識,可實現主線程給子線程(非主線程)發送消息。
把下面例子中的mHandler聲明成類成員,在主線程經過mHandler發送消息便可。
Android官方文檔中Looper的介紹:
Class used to run a message loop for a thread. Threads by default do not have a message loop associated with them; to create one, call prepare() in the thread that is to run the loop, and then loop() to have it process messages until the loop is stopped.
Most interaction with a message loop is through the Handler class.
This is a typical example of the implementation of a Looper thread, using the separation of prepare() and loop() to create an initial Handler to communicate with the Looper.
01 |
class LooperThread extends Thread { |
02 |
public Handler mHandler; |
07 |
mHandler = new Handler() { |
08 |
public void handleMessage(Message msg) { |
09 |
// process incoming messages here |