什麼是Handler
handler通俗講就是在各個進程之間發送數據的處理對象。在任何進程中,只要獲得了另一個進程的handler則可以通過 handler.sendMessage(message)方法向那個進程發送數據。基於這個機制,我們在處理多線程的時候可以新建一個thread,這 個thread擁有UI線程中的一個handler。當thread處理完一些耗時的操作後通過傳遞過來的handler向UI線程發送數據,由UI線程去更新界面。
Handler類簡介
在Android平台中,新啟動的線程是無法訪問Activity裡的Widget的,當然也不能將運行狀態外送出來,這就需要有Handler機 制進行消息的傳遞了,Handler類位於android.os包下,主要的功能是完成Activity的Widget與應用程序中線程之間的交互。接下 來對該類中常用的方法進行介紹,如下表所示。
Handler類的常用方法
方法簽名
描 述
public void handleMessage (Message msg)
子類對象通過該方法接收信息
public final boolean sendEmptyMessage (int what)
發送一個只含有 what 值的消息
public final boolean sendMessage (Message msg)
發送消息到 Handler ,
通過 handleMessage 方法接收
public final boolean hasMessages (int what)
監測消息隊列中是否還
有 what 值的消息
public final boolean post (Runnable r)
將一個線程添加到消息隊列
開發帶有Handler類的程序步驟如下。
在Activity或Activity的Widget中開發Handler類的對象,並重寫handleMessage方法。
在新啟動的線程中調用sendEmptyMessage或者sendMessage方法向Handler發送消息。
Handler類的對象用handleMessage方法接收消息,然後根據消息的不同執行不同的操作。
在Android 中Handler和Message、Thread有著很密切的關系。Handler 主要是負責Message的分發和處理。但是這個Message從哪裡來的呢?Message 由一個消息隊列進行管理,而消息隊列卻由一個Looper進行管理。Android系統中Looper負責管理線程的消息隊列和消息循環,具體實現請參考Looper的源碼。 可以通過Loop.myLooper()得到當前線程的Looper對象,通過Loop.getMainLooper()可以獲得當前進程的主線程的 Looper對象。Android系統的消息隊列和消息循環都是針對具體線程的,一個線程可以存在(當然也可以不存在)一個消息隊列和一個消 息循環(Looper),特定線程的消息只能分發給本線程,不能進行跨線程,跨進程通訊。但是創建的工作線程默認是沒有消息循環和消息隊列的,如果想讓該 線程具有消息隊列和消息循環,需要在線程中首先調用Looper.prepare()來創建消息隊列,然後調用Looper.loop()進入消息循環。
雖說 特定線程的消息只能分發給本線程,不能進行跨線程通訊,但是由於可以通過獲得線程的Looper對象來進行曲線的實現不同線程間消息的傳遞,代碼如下
package com.mytest.handlertest;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;
public class HandlerTest extends Activity implements OnClickListener{
private String TAG = "HandlerTest";
private boolean bpostRunnable = false;
private NoLooperThread noLooperThread = null;
private OwnLooperThread ownLooperThread = null;
private ReceiveMessageThread receiveMessageThread =null;
private Handler mOtherThreadHandler=null;
private EventHandler mHandler = null;
private Button btn1 = null;
private Button btn2 = null;
private Button btn3 = null;
private Button btn4 = null;
private Button btn5 = null;
private Button btn6 = null;
private TextView tv = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(250, 50);
layout.setOrientation(LinearLayout.VERTICAL);
btn1 = new Button(this);
btn1.setId(101);
btn1.setText("message from main thread self");
btn1.setOnClickListener(this);
layout.addView(btn1, params);
btn2 = new Button(this);
btn2.setId(102);
btn2.setText("message from other thread to main thread");
btn2.setOnClickListener(this);
layout.addView(btn2,params);
btn3 = new Button(this);
btn3.setId(103);
btn3.setText("message to other thread from itself");
btn3.setOnClickListener(this);
layout.addView(btn3, params);
btn4 = new Button(this);
btn4.setId(104);
btn4.setText("message with Runnable as callback from other thread to main thread");
btn4.setOnClickListener(this);
layout.addView(btn4, params);
btn5 = new Button(this);
btn5.setId(105);
btn5.setText("main thread's message to other thread");
btn5.setOnClickListener(this);
layout.addView(btn5, params);
btn6 = new Button(this);
btn6.setId(106);
btn6.setText("exit");
btn6.setOnClickListener(this);
layout.addView(btn6, params);
tv = new TextView(this);
tv.setTextColor(Color.WHITE);
tv.setText("");
params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT);
params.topMargin=10;
layout.addView(tv, params);
setContentView(layout);
receiveMessageThread = new ReceiveMessageThread();
receiveMessageThread.start();
}
class EventHandler extends Handler{
public EventHandler(Looper looper){
super(looper);
}
public EventHandler(){
super();
}
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId());
switch(msg.what){
case 1:
tv.setText((String)msg.obj);
break;
case 2:
tv.setText((String)msg.obj);
noLooperThread.stop();
break;
case 3:
//不能在非主線程的線程裡面更新UI,所以這裡通過log打印信息
Log.e(TAG,(String)msg.obj);
ownLooperThread.stop();
break;
default:
Log.e(TAG,(String)msg.obj);
break;
}
}
}
//ReceiveMessageThread has his own message queue by execute Looper.prepare();
class ReceiveMessageThread extends Thread {
@Override
public void run(){
Looper.prepare();
mOtherThreadHandler= new Handler(){
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
Log.e(TAG,"-------+>"+(String)msg.obj);
Log.e(TAG, "CurrentThread id:----------+>" + Thread.currentThread().getId());
}
};
Log.e(TAG, "ReceiveMessageThread id:--------+>" + this.getId());
Looper.loop();
}
}
class NoLooperThread extends Thread {
private EventHandler mNoLooperThreadHandler;
@Override
public void run() {
Looper myLooper = Looper.myLooper();
Looper mainLooper= Looper.getMainLooper();
String msgobj;
if(null == myLooper){
//這裡獲得的是主線程的Looper,由於NoLooperThread沒有自己的looper所以這裡肯定會被執行
mNoLooperThreadHandler = new EventHandler(mainLooper);
msgobj = "NoLooperThread has no looper and handleMessage function executed in main thread!";
} else{
mNoLooperThreadHandler = new EventHandler(myLooper);
msgobj = "This is from NoLooperThread self and handleMessage function executed in NoLooperThread!";
}
mNoLooperThreadHandler.removeMessages(0);
if(bpostRunnable == false){
//send message to main thread
Message msg = mNoLooperThreadHandler.obtainMessage(2, 1, 1, msgobj);
mNoLooperThreadHandler.sendMessage(msg);
Log.e(TAG, "NoLooperThread id:--------+>" + this.getId());
}else{
//下面new出來的實現了Runnable接口的對象中run函數是在Main Thread中執行,不是在NoLooperThread中執行 記得 null == myLooper麼
//注意Runnable是一個接口,它裡面的run函數被執行時不會再新建一個線程
//您可以在run上加斷點然後在eclipse調試中看它在哪個線程中執行
mNoLooperThreadHandler.post(new Runnable(){
public void run() {
// TODO Auto-generated method stub
tv.setText("update UI through handler post runnalbe mechanism!");
Log.e(TAG, "update UI id:--------+>" + Thread.currentThread().getId());
noLooperThread.stop();
}
});
}
}
}
class OwnLooperThread extends Thread{
private EventHandler mOwnLooperThreadHandler = null;
@Override
public void run() {
Looper.prepare();
Looper myLooper = Looper.myLooper();
Looper mainLooper= Looper.getMainLooper();
String msgobj;
if(null == myLooper){
mOwnLooperThreadHandler = new EventHandler(mainLooper);
msgobj = "OwnLooperThread has no looper and handleMessage function executed in main thread!";
}else{
mOwnLooperThreadHandler = new EventHandler(myLooper);
msgobj = "This is from OwnLooperThread self and handleMessage function executed in NoLooperThread!";
}
mOwnLooperThreadHandler.removeMessages(0);
//給自己發送消息
Message msg = mOwnLooperThreadHandler.obtainMessage(3,1,1,msgobj);
mOwnLooperThreadHandler.sendMessage(msg);
Looper.loop();
}
}
public void onClick(View v) {
// TODO Auto-generated method stub
switch(v.getId()){
case 101:
//主線程發送消息給自己
Looper looper = Looper.myLooper();//get the Main looper related with the main thread
//如果不給任何參數的話會用當前線程對應的Looper(這裡就是Main Looper)為Handler裡面的成員mLooper賦值
mHandler = new EventHandler(looper);
// 清除整個MessageQueue裡的消息
mHandler.removeMessages(0);
String obj = "This main thread's message and received by itself!";
Message msg = mHandler.obtainMessage(1,1,1,obj);
// 將Message對象送入到main thread的MessageQueue裡面
mHandler.sendMessage(msg);
break;
case 102:
//other線程發送消息給主線程
bpostRunnable = false;
noLooperThread = new NoLooperThread();
noLooperThread.start();
break;
case 103:
//other thread獲取它自己發送的消息
tv.setText("please look at the error level log for other thread received message");
ownLooperThread = new OwnLooperThread();
ownLooperThread.start();
break;
case 104:
//other thread通過Post Runnable方式發送消息給主線程
bpostRunnable = true;
noLooperThread = new NoLooperThread();
noLooperThread.start();
break;
case 105:
//主線程發送消息給other thread
if(null!=mOtherThreadHandler){
tv.setText("please look at the error level log for other thread received message from main thread");
String msgObj = "message from mainThread";
Message mainThreadMsg = mOtherThreadHandler.obtainMessage(1, 1, 1, msgObj);
mOtherThreadHandler.sendMessage(mainThreadMsg);
}
break;
case 106:
finish();
break;
}
}
}