一個Handler允許你發送和處理消息(Message)以及與一個線程的消息隊列相關的Runnable對象。每個Handler實例都和單個線程以及該線程的消息隊列有關。當你創建了一個新Handler,它就會和創建它的線程/消息隊列綁定,在那以後,它就會傳遞消息以及runnable對象給消息隊列,然後執行它們。
需要使用Handler有兩大主要的原因:
(1)在將來的某個時間點調度處理消息和runnable對象;
(2)將需要執行的操作放到其他線程之中,而不是自己的;
調度處理消息是通過調用post(Runnable),
postAtTime(Runnable, long), postDelayed(Runnable, long), sendEmptyMessage(int), sendMessage(Message), sendMessageAtTime(Message, long)和sendMessageDelayed(Message,
long)等方法完成的。其中的post版本的方法可以讓你將Runnable對象放進消息隊列;sendMessage版本的方法可以讓你將一個包含有bundle對象的消息對象放進消息隊列,然後交由handleMessage(Message)方法處理。(這個需要你複寫Handler的handleMessage方法)
【以上這段翻譯自android
sdk】
Handler在實際開發中是很常用的,主要是用來接收子線程發送的數據,然後主線程結合此數據來更新界面UI。
Android應用程序啓動時,他會開啓一個主線程(也就是UI線程),管理界面中的UI控件,進行事件派發,比如說:點擊一個按鈕,Android會分發事件到Button上從而來響應你的操作。但是當你需要執行一個比較耗時的操作的話,例如:進行IO操作,網絡通信等等,若是執行時間超過5s,那麼Android會彈出一個“經典”的ANR無響應對話框,然後提示按“Force quit”或是“Wait”。解決此類問題的方法就是:我們把一些耗時的操作放到子線程中去執行。但因爲子線程涉及到UI更新,而Android主線程是線程不安全的,所以更新UI的操作只能放在主線程中執行,若是放在子線程中執行的話很會出問題。所以這時就需要一種機制:主線程可以發送“命令/任務”給子線程執行,然後子線程反饋執行結果;
!你必需要知道的:
若在主線程中實例化一個Handler對象,例如:
Handler mHandler = new Handler();
此時它並沒有新派生一個線程來執行此Handler,而是將此Handler附加在主線程上,故此時若你在Handler中執行耗時操作的話,還是會彈出ANR對話框!
下面就Handler的使用舉一些例子,加深理解。1、post版本的Handler使用示例:
package com.dxyh.test;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class MainActivity extends Activity
implements OnClickListener {
private final static String TAG = "HandlerTest";
private final static int DELAY_TIME = 1000;
private Button btnStart;
private Button btnStop;
Context mContext = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mContext = this;
Log.i(TAG, "Main thread id = " +
Thread.currentThread().getId());
btnStart = (Button) findViewById(R.id.btn_start);
btnStart.setOnClickListener(this);
btnStop = (Button) findViewById(R.id.btn_stop);
btnStop.setOnClickListener(this);
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btn_start:
mHandler.postDelayed(workRunnable, DELAY_TIME);
break;
case R.id.btn_stop:
mHandler.removeCallbacks(workRunnable);
break;
}
}
Runnable workRunnable = new Runnable() {
int counter = 0;
public void run() {
if (counter++ < 1) {
Log.i(TAG, "workRunnable thread id = " +
Thread.currentThread().getId());
mHandler.postDelayed(workRunnable, DELAY_TIME);
}
}
};
Handler mHandler = new Handler();
}
Logcat顯示如下:
說明:發現thread id是相同的,這就說明:默認情況下創建的Handler會綁定到主線程上,你不能做太耗時的操作。