1. 程式人生 > >Android 多執行緒程式設計:Handler訊息傳遞機制—重新整理UI主介面

Android 多執行緒程式設計:Handler訊息傳遞機制—重新整理UI主介面

一、為什麼使用Handler

  當一個Activity執行的時候,會開啟一條主執行緒,主執行緒主要負責處理與UI相關的事件,主執行緒不允許其他子執行緒操控它,更新UI介面。既然不允許我們在子執行緒中操控UI介面,那麼,像我們平時所見的點選獲取驗證碼,不斷更新UI介面的操作又怎樣實現的呢?這裡就用到了我們的Handler訊息傳遞的機制。

二、Handler訊息傳遞機制介紹

Handler類的主要作用有兩個:
1、在新啟動的執行緒中發訊息。
2、在主執行緒中獲取、處理訊息。
也就是執行緒發訊息給主執行緒,在handler中存在一個MessageQueue(訊息佇列),執行緒的訊息發給了MessageQueue,我們再通過Handler類中的handleMessage方法重寫進行相關操作。Handler會不斷的從MessageQueue中獲取並處理訊息。當然除了能從執行緒向主執行緒發訊息,我們也可以從主執行緒向執行緒發訊息,只是這種情況不常見,一般不會這樣做。

補充

三、使用例項

子執行緒向主執行緒發訊息

1、開啟一個新的執行緒,在新的執行緒中new一個Message,設定Message,並由傳送Message
2、主執行緒中接收Handler,並進行UI的更新操作

package com.example.newjc;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.Menu;
import android.view.View;
import
android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity implements OnClickListener{ private Button mbtn_second; private Handler handler=new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what) { case
TIME_DESC: String s=(String) msg.obj; mbtn_second.setText(s); break; default: break; } } }; public static final int TIME_DESC=0x22; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mbtn_second=(Button) findViewById(R.id.bt_second); mbtn_second.setOnClickListener(this); } @Override public void onClick(View v) { new Thread (new Runnable() { @Override public void run() { int count=60; while(count>0){ count--; try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } Message msg=new Message(); msg.obj=count+"秒"; msg.what=TIME_DESC; handler.sendMessage(msg); } } }).start(); } }

這裡寫圖片描述
為了簡化操作,我們對以上程式碼進行修改,採用遞迴思想來實現同樣效果
注意:這裡的程式碼並沒有用到子執行緒,純粹是handler的一種使用方式。

@Override
    public void onClick(View v) {
        count=60;
        //傳送一個空訊息
        handler.sendEmptyMessage(TIME_DESC);
    }
private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
            case TIME_DESC:
                count--;
                mbtn_second.setText(count + "秒");
                if (count > 0) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    handler.sendEmptyMessage(TIME_DESC);
                }
                break;
            default:
                break;
            }
        }
    };

主執行緒給子執行緒發訊息

public class MainActivity extends Activity implements OnClickListener {
    private Button mbtn_second;
    private Button mbtn_second2;
    private int count;
    private  Mythread thread;
    public static final int TIME_DESC = 0x22;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mbtn_second = (Button) findViewById(R.id.bt_second);
        mbtn_second2 = (Button) findViewById(R.id.bt_second2);
        mbtn_second.setOnClickListener(this);
        mbtn_second2.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        //count = 60;
        //handler.sendEmptyMessage(TIME_DESC);
        switch (v.getId()) {
        case R.id.bt_second:
             thread=new Mythread();
             thread.start();
            break;
        case R.id.bt_second2:
//因為handler需要時間建立,因此不能直接將下面的程式碼放在 //thread.start();下面,放在他下面會報空指標

             thread.handler.sendEmptyMessage(0);
            break;
        default:
            break;
        }

    //   thread.handler.sendEmptyMessage(0);
    }
    class Mythread extends Thread{
    private Handler handler;
      @Override
    public void run() {
    //handler—send-MessageQueue-looper讀取—hangleMessage操作
    //looper是主執行緒中預設使用,因此在子執行緒向主執行緒發訊息的時候沒有新增
    //但是子執行緒不具有,因此必須寫出
        Looper.prepare();
        handler=new Handler(){          
        @Override
        public void handleMessage(Message msg) {
            Log.d("主執行緒給子執行緒", "主執行緒給子執行緒");            
        }
        };
        Looper.loop();
    }
}
}