Android單執行緒模型中Message、Handler、Message Queue、Looper之間的關係
阿新 • • 發佈:2019-02-01
四者之間的關係:
Handler獲取當前執行緒中的looper物件,looper用來從存放Message的MessageQueue中取出Message,再有Handler進行Message的分發和處理.簡單定義:
1、Message Queue(訊息佇列): 用來存放通過Handler釋出的訊息,通常附屬於某一個建立它的執行緒,可以通過Looper.myQueue()得到當前執行緒的訊息佇列.2、Handler: 可以釋出或者處理一個訊息或者操作一個Runnable,通過Handler釋出訊息,訊息將只會傳送到與它關聯的訊息佇列,然也只能處理該訊息佇列中的訊息. 3、Looper: 是Handler和訊息佇列之間通訊橋樑,程式元件首先通過Handler把訊息傳遞給Looper,Looper把訊息放入佇列。Looper也把訊息佇列裡的訊息廣播給所有的Handler:Handler接受到訊息後呼叫handleMessage進行處理.
4、Message: 訊息的型別,在Handler類中的handleMessage方法中得到單個的訊息進行處理,在單執行緒模型下,為了執行緒通訊問題,Android設計了一個Message Queue(訊息佇列), 執行緒間可以通過該Message Queue並結合Handler和Looper元件進行資訊交換。
詳細介紹:
原始碼:
- publicclass MainActivity extends Activity implements OnClickListener {
- private Button startbutton = null;
- private TextView text = null;
- private MyHandler mHandler = null;
- private Thread thread;
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
-
super
- setContentView(R.layout.main);
- startbutton = (Button) findViewById(R.id.StartButton);
- startbutton.setOnClickListener(this);
- text = (TextView) findViewById(R.id.content);
- }
- @Override
- publicvoid onClick(View v) {
- switch (v.getId()) {
- case R.id.StartButton:
- // 每次單擊都會建立一個新的執行緒,這肯定是不合適的
- thread = new MyThread();
- thread.start();// 開啟一個子執行緒
- break;
- }
- }
- privateclass MyHandler extends Handler {
- public MyHandler(Looper looper) {
- super(looper);
- }
- @Override
- publicvoid handleMessage(Message msg) { // 處理訊息
- System.out
- .println("handle--id-->" + Thread.currentThread().getId());// 1
- System.out.println("handle--name-->"
- + Thread.currentThread().getName());// main
- text.setText(msg.obj.toString());// 此時handle在主執行緒當中,可以處理介面更新
- }
- }
- /**
- * Android 會自動替主執行緒建立Message Queue ,在這個子執行緒裡並沒有建立Message Queue 。 所以,myLooper
- * 值為null ,而mainLooper 則指向主執行緒裡的Looper 。於是,執行到: mHandler = new MyHandler
- * (mainLooper); 此mHandler屬於主執行緒。 mHandler.sendMessage(m);
- * @author andieguo
- */
- privateclass MyThread extends Thread {
- /**
- * Looper.myLooper();獲得當前的Looper Looper.getMainLooper ();獲得UI執行緒的Lopper
- */
- @Override
- publicvoid run() {
- System.out.println("MyThread------id------>"
- + Thread.currentThread().getId());
- System.out.println("MyThread------name------>"
- + Thread.currentThread().getName());
- Looper curLooper = Looper.myLooper();// MyThread執行緒
- Looper mainLooper = Looper.getMainLooper();
- String msg;
- if (curLooper == null) {
- // 把當前handler繫結在mainLooper執行緒上;此時mainLooper執行緒當中
- mHandler = new MyHandler(mainLooper);
- msg = "curLooper is null";
- } else {
- mHandler = new MyHandler(curLooper);// 將mHandler與curLooper繫結
- msg = "This is curLooper";
- }
- mHandler.removeMessages(0);
- Message m = mHandler.obtainMessage(1, 1, 1, msg);
- // mHandler物件而將訊息m傳給curLooper,然後放入MessageQueue裡。
- // Looper物件看到MessageQueue裡有訊息m,就將它廣播出去,mHandler物件接到此訊息時,會呼叫其handleMessage()函式來處理
- mHandler.sendMessage(m);// 將訊息新增到了curLooper相關聯的訊息佇列中;
- }
- }
- }