標籤:
基本概念:
Message:訊息,其中包含了訊息ID,訊息處理對象以及處理的資料等,由MessageQueue統一列隊,終由Handler處理。
Handler:處理者,負責Message的發送及處理。使用Handler時,需要實現handleMessage(Message msg)方法來對特定的Message進行處理,例如更新UI等。
MessageQueue:訊息佇列,用來存放Handler發送過來的訊息,並按照FIFO規則執行。當然,存放Message並非實際意義的儲存,而是將Message以鏈表的方式串聯起來的,等待Looper的抽取。
Looper:訊息泵,不斷從MessageQueue中抽取Message執行。因此,一個MessageQueue需要一個Looper。
Thread:線程,負責調度整個訊息迴圈,即訊息迴圈的執行場所。
三步實現線程的訊息處理機制:
1. 用Looper.prepare()建立Looper(訊息泵,不斷從MessageQueue中抽取Message執行(Message Pool大小為10個))
2. 用handler處理訊息
3. 用Looper.loop()進入迴圈
* 主線程預設提供該機制,其它線程預設沒有Looper對象。如果想讓我們新建立的線程擁有Looper對象時,我們首先應線上程run()方法當中調用Looper.prepare()方法,然後再在run()方法最後調用Looper.loop()方法。典型的用法如下:
class LooperThread extends Thread {
public Handler mHandler;
public void run() {
Looper.prepare();
mHandler = new Handler() {
public void handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}
* 倘若我們的線程中已經存在Looper對象,則我們可以通過Looper.myLooper()擷取,此外我們還可以通過Looper.getMainLooper()擷取當前應用系統中主線程的Looper對象。
HandlerThread:
HandlerThread是一個封裝好的帶有looper的線程類,它繼承了Thread類,本質上就是一個線程,在非UI線程中想要實現訊息機制,就可以使用它,步驟如下:
HandlerThread thread = new HandlerThread("MyHandlerThread"); //建立並啟動線程
thread.start();
mHandler = new Handler(thread.getLooper()); //建立Handler對象時將HandlerThread中的looper對象傳入
mHandler.post(new Runnable(){...});
注意事項:
* 當線程A需要發訊息給線程B的時候,線程B要用自己的Looper執行個體化Handler類,線上程中執行個體化Handler時我們需要保證線程當中包含Looper
* 線程A中應執行個體化Message類,再用Handler類的方法sendMessage將該訊息發送給線程B處理(要先執行個體化Handler類)
* 執行個體化Message類的兩種方法:new Message() / 調用Handler類中的obtainmessage()方法(要先執行個體化Handler類)
Message msg = handler.obtainMessage();
msg.arg1 = i;
msg.sendToTarget();
Message msg=new Message();
msg.arg1=i;
handler.sendMessage(msg);
* 第一種寫法是message 從handler 類擷取,從而可以直接向該handler 對象發送訊息,第二種寫法是直接調用 handler 的sendMessage方法發送訊息。
* handler.post(runnable)方法和handler.sendMessage()方法原理相同,只不過是將Runnable轉成一個Message。當不確定當前線程時(不知道傳哪個looper),更新UI時盡量調用View.post(Runnable action)方法。該方法中,View會自動擷取當前線程(即UI線程)的Handler,然後將action對象post到Handler裡。在Handler裡,它將傳遞過來的action對象封裝成一個Message(Message的callback為action),然後將其投入UI線程的訊息迴圈中。在Handler再次處理該Message時,有一條分支(未解釋的那條)就是為它所設,直接調用runnable的run方法。而此時,已經路由到UI線程裡,因此,我們可以毫無顧慮的來更新UI。
Android訊息處理