Handler、Message、Loop訊息佇列模型,各部分的作用
阿新 • • 發佈:2019-01-07
Android系統的訊息佇列和訊息迴圈都是針對具體執行緒的,一個執行緒可以存在(當然也可以不存在)一個訊息佇列(Message Queue)和一個訊息迴圈(Looper)。Android中除了UI執行緒(主執行緒),建立的工作執行緒預設是沒有訊息迴圈和訊息佇列的。如果想讓該執行緒具有訊息佇列和訊息迴圈,並具有訊息處理機制,就需要線上程中首先呼叫Looper.prepare()來建立訊息佇列,然後呼叫Looper.loop()進入訊息迴圈。如以下程式碼所示:
這樣該執行緒就具有了訊息處理機制了。如果不呼叫Looper.prepare()來建立訊息佇列,會報"Java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()"的錯誤。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(); } }
通過下圖可以清晰顯示出UI Thread, Worker Thread, Handler, Massage Queue, Looper之間的關係:
解釋上圖中的幾個基本概念: 1.Message 訊息物件,顧名思義就是記錄訊息資訊的類。這個類有幾個比較重要的欄位:
- Activity.runOnUiThread( Runnable )
- View.post( Runnable )
- View.postDelayed( Runnable, long )
- Handler
package com.superonion;
import android.app.Activity;
import android.os.Bundle;
import android.os.Message;
import android.util.Log;
import android.os.Handler;
public class MyHandler extends Activity {
static final String TAG = "Handler";
Handler h = new Handler(){
public void handleMessage (Message msg)
{
switch(msg.what)
{
case HANDLER_TEST:
Log.d(TAG, "The handler thread id = " + Thread.currentThread().getId() + "\n");
break;
}
}
};
static final int HANDLER_TEST = 1;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "The main thread id = " + Thread.currentThread().getId() + "\n");
new myThread().start();
setContentView(R.layout.main);
}
class myThread extends Thread
{
public void run()
{
Message msg = new Message();
msg.what = HANDLER_TEST;
h.sendMessage(msg);
Log.d(TAG, "The worker thread id = " + Thread.currentThread().getId() + "\n");
}
}
}
以上程式碼中,Handler在主執行緒中建立後,子執行緒通過sendMessage()方法就可以將訊息傳送到主執行緒中,並在handleMessage()方法中處理。 注意:由於Handler為匿名內部類,預設是引用外部例項的。所以我上面的程式碼寫法是有問題的,正確的寫法應該把Handler生明成一個靜態內部類繼承自Handler。這裡由於篇幅原因就不再贅述了。如果感興趣可以檢視我之前的一篇關於Android記憶體洩漏的一篇文章,連結如下:http://blog.csdn.net/longlyboyhe/article/details/48809401。 總結:
- Handler通過sendMessage()傳送Message到MessageQueue佇列;
- Looper通過loop(),不斷提取出達到觸發條件的Message,並將Message交給target來處理;
- 經過dispatchMessage()後,交回給Handler的handleMessage()來進行相應地處理。
- 將Message加入MessageQueue時,處往管道寫入字元,可以會喚醒loop執行緒;如果MessageQueue中沒有Message,並處於Idle狀態,則會執行IdelHandler介面中的方法,往往用於做一些清理性地工作。