android開發-----message

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()
2  
3 public final Message obtainMessage(int what)
4  
5 public final Message obtainMessage(int what, Object obj)
6  
7 public final Message obtainMessage(int what, int arg1, int arg2)
8  
9 public final Message obtainMessage(int what, int arg1, int arg2, Object obj)

obtainmessage()是從消息池中拿來一個msg 不須要另開闢空間new函數

new須要從新申請,效率低,obtianmessage能夠循環利用;工具

[java]  view plain copy
  1. //use Handler.obtainMessage(),instead of msg = new Message();  
  2. //because if there is already an Message object,that not be used by   
  3. //any one ,the system will hand use that object,so you don't have to   
  4. //create and object and allocate memory.  
  5. //it  is also another example of object recycling and reusing in android.  
  6.     Message msg = mHandler.obtainMessage();  
  7.     msg.what = UPDATE_LISTVIEW;  
  8.     msg.obj = current + "/" + total + "songs";  
  9.     //this method is called from worker Thread,so we cannot update UI from here.  
  10.     msg.sendToTarget();  
在看下面代碼:
[java]  view plain copy
  1. Message msg = handler.obtainMessage();  
  2.                         msg.arg1 = i;  
  3.                         msg.sendToTarget();   
  4.   
  5.   
  6. Message msg=new Message();  
  7.     msg.arg1=i;  
  8.     handler.sendMessage(msg);  

第一種寫法是message 從handler 類獲取,從而能夠直接向該handler 對象發送消息,第二種寫法是直接調用 handler 的發送消息方法發送消息。

C、刪除消息

刪除在消息隊列中未處理的消息oop

1 public final void removeMessages(int what)
2  
3 public final void removeMessages(int what, Object object)

D、發送消息post

1 public final boolean sendMessage(Message msg)
2  
3 public final boolean sendMessageDelayed(Message msg, long delayMillis)
4  
5 public final boolean post(Runnable r)
6  
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:

1 public Handler()
2  
3 public Handler(Callback callback)

建立與指定線程相關聯的Handler:

1 public Handler(Looper looper)
2  

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;
03        
04       public void run() {
05           Looper.prepare();
06            
07           mHandler = new Handler() {
08               public void handleMessage(Message msg) {
09                   // process incoming messages here
10               }
11           };
12            
13           Looper.loop();
14       }
15 }
相關文章
相關標籤/搜索