Handler訊息傳遞機制:實現在新建立的線程中操作UI介面
(1)MessageQueue訊息佇列:
MessageQueue用於存放Message,存放的Message按照FIFO(先進先出)的原則執行。MessageQueue被封裝到Looper裡面
(2)Looper迴圈者
在Android中,一個線程對應一個Looper對象,一個Looper對象對應一個MessageQueue。Looper對象用來為一個線程開啟一個訊息迴圈,用來操作MessageQueue。預設情況下,Android新建立的線程是沒有開啟訊息迴圈的(主線程除外)。要想在非主線程中建立Handler對象,首先需要用Looper類的prepare()方法初始化一個Looper對象,然後建立Handler對象,再使用Looper類的loop()方法,啟動Looper,從訊息佇列裡擷取和處理訊息。例如:
public class LooperThread extends Thread{
public Handler handler;
@Override
public void run(){
super.run();
Looper.prepare();
//執行個體化一個Handler對象
handler = new Handler(){
public void handleMessage(Message msg){
Log.i("Looper",String.valueOf(msg.what));
}
};
Message message = handler.obtainMessage(); //擷取訊息
message.what = 0x11; //設定Message的what屬性的值
handler.sendMessage(message); //發送訊息
Looper.loop(); //啟動Looper
}
}
Looper類提供的常用方法
a. prepare():用於初始化Looper
b. loop():調用loop()方法後,Looper線程開始真正工作,它會從訊息佇列裡擷取訊息和處理訊息
c. myLooper():可以擷取當前線程的Looper對象
d. getThread();用於擷取Looper對象所屬的線程
e. quit():用於結束Looper迴圈
備忘:寫在Looper.loop()之後的代碼不會被執行,這個函數內部是一個迴圈,當調用Handler.getLooper().quit()方法後,loop()方法才會終止,其後面的代碼才能得以運行。
(3)Handler訊息處理類
Handler允許發送和處理Message或Runnable對象到其所在的線程的MessageQueue中。Handler的主要作用有:
a. 將Message或Runnable應用post()方法或sendMessage()方法發送到MessageQueue中,在發送時可以指定延遲時間、發送時間或要攜帶的Bundle資料。當MessageQueue迴圈到該Message時,調用相應的Handler對象的handlerMessage()方法對其進行處理。
b. 在子線程和主線程進行通訊,即在背景工作執行緒中與UI線程進行通訊。
備忘:在一個線程中,只能有一個Looper和MessageQueue,但是,可以有多個Handler,且這些Handler可以共用同一個Looper和MessageQueue。
Handler類同的發送和處理訊息的常用方法有:
a. handleMessage(Message msg):處理訊息的方法。通常重寫該方法來處理訊息,在發送訊息時,該方法會自動回調。
b. post(Runnable r):立即發送Runnable對象,該Runnable對象最後將被封裝成Message對象。
c. postAtTime(Runnable r,long uptimeMillis):定時發送Runnable對象
d. postDelayed(Runnable r,long delayMillis):延遲delayMillis毫秒發送Runnable對象
e. sendEmptyMessage(int what):發送空訊息
f. sendMessage(Message msg):立即發送訊息
g. sendMessageAtTime(Message msg, long uptimeMillis):定時發送訊息
h. sendMessageDelayed(Message msg, long delayMillis):延遲多少毫秒發送訊息
(4)Message訊息類
Message被存放在MessageQueue中,一個MessageQueue中可以包含多個Message對象。每個Message對象可以通過Message.obtain()或者Handler.obtainMessage()方法獲得。Message對象具有如下5個屬性:
a. arg1:int類型,用來存放整型資料
b. arg2;int類型,用來存放整型資料
c. obj:Object類型,用來存放發送給接收器的Object類型的任意對象
d. replyTo;Messenger類型,用來指定此Message發送到何處的可選Message對象
e. what:int類型,用來指定使用者自訂的訊息代碼,這樣接收者可以瞭解這個訊息的資訊。
備忘;使用Message類的屬性可以攜帶int型資料,如果要攜帶其他類型的資料,可以先將要攜帶的資料儲存到Bundle對象中,然後通過Message類的setData()方法將其添加到Message中。
注意:
a. 通常情況下,使用Message.obtian()方法或Handler.obtainMessage()方法從訊息池中獲得空訊息對象,以節省資源。
b. 如果一個Message只需攜帶簡單的int型資訊,應優先使用Message.arg1和Message.arg2屬性來傳遞資訊,這比用Bundle更省記憶體。
c. 儘可能使用Message.what來標識資訊,以便用不同方式處理Message。