Android 多執行緒程式設計:Handler訊息傳遞機制—重新整理UI主介面
阿新 • • 發佈:2019-02-06
一、為什麼使用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();
}
}
}