常見問題2016/09/13

【APP開發】Android Message機制的靈活應用

一、執行緒間通訊的Message機制

1、Message介紹

frameworks\base\core\java\android\Os\Message.java

Message是執行緒之間傳遞資訊的載體,包含了對訊息的描述和任意的資料物件。Message中包含了兩個額外的 int欄位和一個object欄位,這樣在大部分情況下,使用者就不需要再做記憶體分配工作了。雖然Message的建構函式是public的,但是最好是使用Message.obtain( )或Handler.obtainMessage( )函式來獲取Message物件,因為Message的實現中包含了回收再利用的機制,可以提供效率。

2、MessageQueue介紹

frameworks\base\core\java\android\Os\MessageQueue.java

MessageQueue用來容納Message佇列的,其中的Message是由Looper來分發的,Message不能直接新增到MessageQueue中,而是要通過與Looper關聯的Handler去新增。

3、Looper

frameworks\base\core\java\android\Os\Looper.java

Looper是執行緒用來執行訊息迴圈的。執行緒本身是沒有訊息迴圈的,需要線上程中呼叫perpare函式,然後呼叫loop去處理訊息。在Android中,系統在啟動主執行緒的時候會自動為之建立一個Looper。

建立本執行緒的Looper:

public static final void prepare()

執行本執行緒的Looper:

public static final void loop()

獲取本執行緒的Looper:

public static final Looper myLooper()

獲取主執行緒的Looper:

public synchronized static final Looper getMainLooper()

4、Handler

frameworks\base\core\java\android\Os\Handler.java

Handler是用來發送和處理與執行緒相關聯的Message和Runnable物件的。每個Handler都與一個單獨的執行緒以及執行緒訊息佇列相關聯的。當你建立Handler時,Handler就與執行緒以及執行緒訊息佇列繫結了,從那以後,Handler就可以將 Message和Runnable傳送給對應的訊息佇列,並且能夠處理從訊息佇列中出來的訊息。

Handler提供了使用者需要呼叫的大部分介面

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)

B、建立訊息

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)

C、刪除訊息

刪除在訊息佇列中未處理的訊息

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

D、傳送訊息

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)

E、處理訊息

在Looper的loop函式中迴圈取出MessageQueue的接收訊息佇列中的訊息,然後呼叫Hander的dispatchMessage函式對訊息進行處理,至於如何處理(相應訊息)則由使用者指定(三個方法,優先順序從高到低:Message裏面的Callback,一個實現了Runnable介面的物件,其中run函式做處理工作;Handler裏面的mCallback指向的一個實現了Callback介面的物件,裏面的handleMessage進行處理;處理訊息 Handler物件對應的類繼承並實現了其中handleMessage函式,通過這個實現的handleMessage函式處理訊息)。

01 public void dispatchMessage(Message msg) {
02  
03 if (msg.callback != null) {
04  
05        handleCallback(msg);
06  
07     } else {
08        if (mCallback != null) {
09          if (mCallback.handleMessage(msg)) {
10             return;
11          }
12        }
13  
14        handleMessage(msg);
15 }
16 }

二、Message機制的用途

Message機制有兩種用途:

定時執行:延遲到指定時間執行訊息排程

執行緒通訊:將某些操作在其他執行緒中排隊執行

1、定時執行

通過本執行緒的Handler將訊息延遲到指定時間執行,相當於定時器的作用

1 public final boolean sendMessageDelayed(Message msg, long delayMillis)
2  
3 public final boolean postDelayed(Runnable r, long delayMillis)

還可以在指定時間到期之前,通過removeMessages取消執行

2、執行緒通訊

Android的UI是單執行緒的,Android希望UI執行緒能夠給予User快速的反應,如果UI執行緒花費太多的時間做幕後的事情,吵過5秒鐘,Android就會給出錯誤提示。因此爲了避免拖住UI,一下較費時的工作應該交給獨立的執行緒去執行。但是如果幕後的執行緒來執行UI物件,Android又會發出錯誤資訊,所以UI執行緒與幕後執行緒需要進行通訊。UI執行緒將工作分發給幕後執行緒,幕後執行緒執行後將相應的狀態返回給UI執行緒,讓UI執行緒對UI做成相應的更新。

 

本文來自新浪部落格