Android Handler的使用一


一個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)方法處理。(這個需要你複寫HandlerhandleMessage方法)

【以上這段翻譯自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的使用舉一些例子,加深理解。

1post版本的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會綁定到主線程上,你不能做太耗時的操作。

 


發佈了54 篇原創文章 · 獲贊 17 · 訪問量 28萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章