Android Handler

Handler的作用:

主要接受子線程發送的數據, 並用此數據配合主線程更新UI. Android主線程 (也就是UI線程) 操作5秒鐘還沒有完成的話,

界面會出現假死現象,會收到Android系統的一個錯誤提示 “強制關閉”. 這個時候我們需要把這些耗時的操作,放在一個子

線程中

Android不允許子線程更新主線程維護的UI組件,這樣對主線程是不安全的,也就是說,更新UI隻能在主線程中更新,子

線程中操作是危險的.

Handler為android系統的線程通信工具,承擔著主線程與分線程,分線程之間的通信功能,經常用到的有post(),

sendMessage() 方法,前者是將一個線程加入線程隊列,後者是發送一個消息到消息隊列中

Handler主要用於異步消息的處理:當發出一個消息之後,首先進入一個消息隊列,發送消息的函數即刻返回,而另外

個部分逐個的在消息隊列中將消息取出,然後對消息進行處理,就是發送消息和接收消息不是同步的處理。這種機制通

常用來處理相對耗時比較長的操作。

Handler的特點:

Handler綁定的有兩個隊列,一個為消息隊列,另一個為線程隊列。Handler可以通過這兩個隊列來分別:

發送、接受、處理消息–消息隊列;

啟動、結束、休眠線程–線程隊列;

Android OS中,在主線程中創建新的線程,這些新的線程都通過Handler與主線程進行通信。通信通過新線程調用

Handler的post()方法和sendMessage()方法實現,分別對應功能:

post() 將一個線程加入線程隊列;

sendMessage() 發送一個消息對象到消息隊列;

post()方法和sendMessage()還有一些變體,比如postDelayed()、postAtTime()、 sendMessageDelayed ()分別用來延

遲發送、定時發送;

vcD4KPHA+U2VuZE1lc3NhZ2UoKb2rTWVzc2FnZdG5yOvP+8+ittPB0Cy1sc/7z6K208HQ1tDT0M/7z6IsSGFuZGxlTWVzc2FnZSgpu9i197qvyv3E3NfUtq+72LX3LjwvcD4KPHA+UG9zdCgpvavP37PMttTP89G5yOvP37PMttPB0Cy208HQ1tC1xM/fs8y74dLAtM61r7P21MvQ0C48L3A+CjxwPjxicj4KPC9wPgo8cD48c3Ryb25nPkhhbmRsZXK1xMq508O3vbeoOjwvc3Ryb25nPjxicj4KPC9wPgo8cD48c3Ryb25nPkhhbmRsZXIg1tC31reiz/vPorXE0rvQqbe9t6ggIDwvc3Ryb25nPjwvcD4KPHA+cG9zdChSdW5uYWJsZSkgIDwvcD4KPHA+cG9zdEF0VGltZShSdW5uYWJsZSxsb25nKSAgPC9wPgo8cD5wb3N0RGVsYXllZChSdW5uYWJsZSBsb25nKSAgPC9wPgo8cD5zZW5kRW1wdHlNZXNzYWdlKGludCkgIDwvcD4KPHA+c2VuZE1lc3NhZ2UoTWVzc2FnZSkgIDwvcD4KPHA+c2VuZE1lc3NhZ2VBdFRpbWUoTWVzc2FnZSxsb25nKSAgPC9wPgo8cD5zZW5kTWVzc2FnZURlbGF5ZWQoTWVzc2FnZSxsb25nKTwvcD4KPHA+0tTJzyBwb3N0IMDgt723qNTK0O3E48XFwdDSu7j2IFJ1bm5hYmxlILbUz/O1vdb3z9+zzLbTwdDW0CA8L3A+CjxwPnNlbmRNZXNzYWdlIMDgt723qCAsINTK0O3E47CyxcXSu7j2tPjK/b7dtcQgTWVzc2FnZSC21M/ztb2208HQ1tA8L3A+CjxwPjxicj4KPC9wPgo8cD48c3Ryb25nPtPrSGFuZGxlctK7xvC5pNf3tcTX6bz+o7o8L3N0cm9uZz48L3A+CjxwPjxzdHJvbmc+TWVzc2FnZaO6PC9zdHJvbmc+SGFuZGxlcr3TytW6zbSmwO21xM/7z6K21M/zPC9wPgo8cD48c3Ryb25nPkxvb3BlcqO6PC9zdHJvbmc+w7+49s/fs8zWu8Tc07XT0NK7uPZMb29wZXKho8v8tcRsb29wt723qLi61PC2wcihTWVzc2FnZVF1ZXVl1tC1xM/7z6KjrLbBtb3P+8+i1q66877NsNHP+8+ivbu4+Leiy824w8/7z6K1xEhhbmRsZXK9+NDQtKbA7TwvcD4KPHA+PHN0cm9uZz5NZXNzYWdlUXVldWWjujwvc3Ryb25nPs/7z6K208HQo6zL/LLJ08PPyL34z8iz9rXEt73KvcC0udzA7U1lc3NhZ2Who7PM0PK0tL2oTG9vcGVyttTP88qxu+HU2sv8tcS5udTsxvfW0LS0vahNZXNzYWdlUXVldWW21M/zPC9wPgo8cD48c3Ryb25nPkhhbmRsZXKjujwvc3Ryb25nPsv809DBvbj21/fTwy0tt6LLzc/7z6K6zbSmwO3P+8+io6yzzNDyyrnTw0hhbmRsZXK3osvNz/vPoqOssbtIYW5kbGVyt6LLzbXEz/vPorHY0Ouxu8vNtb3WuLaotcRNZXNzYWdlUXVldWWho9Kyvs3Kx8u1o6zI57n7z6PN+0hhbmRsZXLV/bOjuaTX96OssdjQ69TatbHHsM/fs8zW0NPQ0ru49k1lc3NhZ2VRdWV1ZaGjsru5/U1lc3NhZ2VRdWV1ZcrH08lMb29wZXK4utTwudzA7aOs0rK+zcrHy7WjrMjnufvPo837SGFuZGxlctX9s6O5pNf3o6yx2NDr1Nq1scewz9+zzNbQ09DSu7j2TG9vcGVyttTP86GjPC9wPgo8cD48YnI+CjwvcD4KPHA+uenEycbwwLSjrExvb3BlcqOsTWVzc2FnZVF1ZXVlo6xIYW5kbGVyuPfX1LXE1/fTw8jnz8KjujwvcD4KPHA+PHN0cm9uZz5Mb29wZXKjujwvc3Ryb25nPsO/uPbP37PM1rvT0NK7uPZMb29wZXKjrMv8uLrU8LncwO1NZXNzYWdlUXVldWWjrLvhsru2z7XYtNNNZXNzYWdlUXVldWXW0Mihs/bP+8+io6yyor2rz/vPorfWuPi21NOmtcRIYW5kbGVytKbA7aGjPC9wPgo8cD48c3Ryb25nPk1lc3NhZ2VRdWV1ZaO6PC9zdHJvbmc+08lMb29wZXK4utTwudzA7aGjy/yyydPDz8i9+M/Is/a1xLe9yr3AtLncwO1NZXNzYWdloaM8L3A+CjxwPjxzdHJvbmc+SGFuZGxlcqO6PC9zdHJvbmc+y/zE3LDRz/vPoreiy824+Exvb3BlcrncwO21xE1lc3NhZ2VRdWV1ZaOssqK4utTwtKbA7Uxvb3BlcrfWuPjL/LXEz/vPoqGjPC9wPgo8cD48YnI+CjwvcD4KPHA+zqrBy7Gj1qS1scewz9+zzNbQ09BMb29wZXK21M/zv8nS1LfWyOfPwsG91tbH6b/2tKbA7aOsPC9wPgo8cD4gIDxzdHJvbmc+1vdVSc/fs8zW0Dwvc3Ryb25nPqOsz7XNs9LRvq2z9cq8u6/By9K7uPZMb29wZXK21M/zo6zS8rTLs8zQ8taxvdO0tL2oSGFuZGxlcry0v8mjrMi7uvO+zb/Jzai5/UhhbmRsZXLAtLeiy83P+8+io6y0psDtz/vPoqGjo6jI58/CtdrSu7j2s8zQ8qOpPC9wPgo8cD4gIDxzdHJvbmc+s8zQ8tSx19S8usb0tq+1xNfTz9+zzDwvc3Ryb25nPqOss8zQ8tSxsdjQ69fUvLq0tL2o0ru49kxvb3BlcrbUz/OjrLKixvS2r8v8oaO0tL2oTG9vcGVyttTP87X308PL/LXEcHJlcGFyZSgpt723qLy0v8mho6OoyOfPwrXatv649rPM0PKjqTwvcD4KPHA+t9ax8LbU06bI58/Cwb249sD919OzzNDyoaM8L3A+CjxwPjwvcD4KPHByZSBjbGFzcz0=”brush:java;”>public class TestBarHandler extends Activity {
/** Called when the activity is first created. */
// 聲明控件變量
ProgressBar bar = null;
Button startButton = null;

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 根據控件的ID得到代表控件的對象,並為按鈕設置監聽器
bar = (ProgressBar) findViewById(R.id.bar);
startButton = (Button) findViewById(R.id.startButton);
startButton.setOnClickListener(new ButtonListener());
}

// 當點擊startButton按鈕時,就會執行ButtonListener的onClick方法
class ButtonListener implements OnClickListener {

@Override
public void onClick(View v) {
// TODO Auto-generated method stub
bar.setVisibility(View.VISIBLE);
updateBarHandler.post(updateThread);
}

}

// 使用匿名內部類來復寫Handler當中的handleMessage方法
Handler updateBarHandler = new Handler() {

@Override
public void handleMessage(Message msg) {
bar.setProgress(msg.arg1);
updateBarHandler.post(updateThread);
}

};
// 線程類,該類使用匿名內部類的方式進行聲明
Runnable updateThread = new Runnable() {
int i = 0;

@Override
public void run() {
System.out.println(“Begin Thread”);
i = i + 10;
// 得到一個消息對象,Message類是有Android操作系統提供
Message msg = updateBarHandler.obtainMessage();
// 將msg對象的arg1參數的值設置為i,用arg1和arg2這兩個成員變量傳遞消息,優點是系統性能消耗較少
msg.arg1 = i;
try {
// 設置當前顯示睡眠1秒
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// 將msg對象加入到消息隊列當中
updateBarHandler.sendMessage(msg);
if (i == 100) {
// 如果當i的值為100時,就將線程對象從handler當中移除
updateBarHandler.removeCallbacks(updateThread);
}
}
};

}

在線程中使用Handler的步驟如下:

調用Looper的prepare()方法為當前線程創建Looper對象,創建Looper對象時,它的構造器會創建與之配套的MessageQueue。

有瞭Looper之後,創建Handler子類的實例,重寫handleMessage()方法,該方法負責處理來自其他線程的消息。

調用Looper的Looper()方法啟動Looper。

public class CalPrime extends Activity {
	static final String UPPER_NUM = "upper";
	EditText etNum;
	CalThread calThread;

	// 定義一個線程類
	class CalThread extends Thread {
		public Handler mHandler;

		public void run() {
			Looper.prepare();
			mHandler = new Handler() {
				// 定義處理消息的方法
				@Override
				public void handleMessage(Message msg) {
					if (msg.what == 0x123) {
						int upper = msg.getData().getInt(UPPER_NUM);
						List nums = new ArrayList();
						// 計算從2開始、到upper的所有質數
						outer: for (int i = 2; i <= upper; i++) {
							// 用i處於從2開始、到i的平方根的所有數
							for (int j = 2; j <= Math.sqrt(i); j++) {
								// 如果可以整除,表明這個數不是質數
								if (i != 2 && i % j == 0) {
									continue outer;
								}
							}
							nums.add(i);
						}
						// 使用Toast顯示統計出來的所有質數
						Toast.makeText(CalPrime.this, nums.toString(),
								Toast.LENGTH_LONG).show();
					}
				}
			};
			Looper.loop();
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		etNum = (EditText) findViewById(R.id.etNum);
		calThread = new CalThread();
		// 啟動新線程
		calThread.start();
	}

	// 為按鈕的點擊事件提供事件處理函數
	public void cal(View source) {
		// 創建消息
		Message msg = new Message();
		msg.what = 0x123;
		Bundle bundle = new Bundle();
		bundle.putInt(UPPER_NUM, Integer.parseInt(etNum.getText().toString()));
		msg.setData(bundle);
		// 向新線程中的Handler發送消息
		calThread.mHandler.sendMessage(msg);
	}
}

發佈留言