Android 開發(fā)之道(10)Handler本質(zhì)簡(jiǎn)析與使用實(shí)例
1 Overview
先淺析本質(zhì)太過(guò)抽象,還是先上 Handler 的最簡(jiǎn)實(shí)例吧。
- 功能:
Android.os.Handler
負(fù)責(zé)接收,并按計(jì)劃發(fā)送和處理消息; - 特點(diǎn):處理消息是阻塞式的;
- 本質(zhì):關(guān)于
Handler
的內(nèi)部機(jī)制,及其與Looper
的關(guān)系,請(qǐng)看本文的第三部分“消息處理機(jī)制的本質(zhì)”。
2 Get Started
2.1 先創(chuàng)建一個(gè) Handler 對(duì)象,
private Handler mHandler = new Handler();
但這樣的Handler
是沒(méi)用的。不過(guò)先暫且不要管,往下面看。
2.2 向 Handler 的消息隊(duì)列發(fā)送數(shù)據(jù)
發(fā)送數(shù)據(jù)的動(dòng)作是通過(guò) sendMessage 完成的。
Message message = new Message();
message.what = 1;
// 將消息發(fā)送到mHandler的消息隊(duì)列的最后
mHandler.sendMessage(message);
不過(guò)實(shí)際上,在 Handler 內(nèi)部有一個(gè) Looper 類,而消息隊(duì)列其實(shí)是 Looper 的一個(gè)成員。Handler 中的 mQueue 就是其成員 mLooper 的 mQueue。
2.3 處理消息隊(duì)列中的數(shù)據(jù)
Handler 可以根據(jù) Message 中的 what 值的不同來(lái)分發(fā)處理,Handler 中提供了 handleMessage 來(lái)讓開發(fā)人員進(jìn)行 Override。示例如下:
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 所做的操作
break;
case 2:
// 所做的操作
break;
default:
// 所做的操作
}
};
完整的寫法,就是在創(chuàng)建 Handler 對(duì)象時(shí)如下:
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 所做的操作
break;
case 2:
// 所做的操作
break;
default:
// 所做的操作
}
};
}
2 計(jì)時(shí)器簡(jiǎn)例
2.1 先創(chuàng)建一個(gè)任務(wù)類
Timer 和 TimerTask 是 Java 語(yǔ)言中的類,如果不熟悉,請(qǐng)看下面的例子及注視。
// 任務(wù)類
private class MyTask extends TimerTask{
@Override
public void run() {
// 創(chuàng)建要發(fā)送的消息
Message message = new Message();
message.what = 1;
// 將消息發(fā)送到mHandler的消息隊(duì)列的最后
mHandler.sendMessage(message);
}
}
使用方法很簡(jiǎn)單,就是用 Timer 來(lái)作為容器:
// 創(chuàng)建用于執(zhí)行任務(wù)類的Timer
Timer timer = new Timer();
// 1毫秒之后開始每隔5秒鐘執(zhí)行一次MyTast
timer.scheduleAtFixedRate(new MyTask(), 1, 1000);
2.2 完整的例子
布局文件就省略了,源碼如下:
package com.sinosuperman.android;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
public class Test extends Activity {
//title為setTitle方法提供變量,這里為了方便我設(shè)置成了int型
private int mSecs = 0;
private Handler mHandler = new Handler(){
// 根據(jù)mHandler的消息隊(duì)列中的不同消息進(jìn)行處理
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 所做的操作
updateTitle();
break;
}
};
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 創(chuàng)建用于執(zhí)行任務(wù)類的Timer
Timer timer = new Timer();
// 1毫秒之后開始每隔5秒鐘執(zhí)行一次MyTast
timer.scheduleAtFixedRate(new MyTask(), 1, 1000);
}
// 任務(wù)類
private class MyTask extends TimerTask{
@Override
public void run() {
// 創(chuàng)建要發(fā)送的消息
Message message = new Message();
message.what = 1;
// 將消息發(fā)送到mHandler的消息隊(duì)列的最后
mHandler.sendMessage(message);
}
}
// 處理消息所做的操作
public void updateTitle(){
setTitle("Michael's Timer: " + mSecs);
mSecs++;
}
}
3 消息處理機(jī)制的本質(zhì)
3.1 Looper 與 Handler 的內(nèi)部機(jī)制
Looper 中有一個(gè) MessageQueue 的成員,Looper 中還有有一個(gè) loop 函數(shù)用來(lái)對(duì)消息隊(duì)列進(jìn)行循環(huán)。Looper 并不直接與 Handler 綁定,我們可以直接“玩弄” Looper,不過(guò) Handler 讓我們“玩弄”她更容易一些。
Handler 本質(zhì)上是一個(gè)工具類,其內(nèi)部有 Looper 成員。我們通過(guò) Handler 類完成消息的發(fā)送和處理、制定分發(fā)機(jī)制等等。
3.2 消息處理機(jī)制的本質(zhì)
Handler 中封裝了 Looper 成員,Handler 中的消息隊(duì)列就是 Looper 中的消息隊(duì)列成員。Looper 中有消息的循環(huán)分發(fā)機(jī)制。下面介紹下內(nèi)部的大致流程:
- 當(dāng)將一個(gè)消息通過(guò) sendMessage 交給 Handler 的時(shí)候,就是交給了 Looper;
- Looper 將消息發(fā)送到這個(gè)消息指定的 target,而這個(gè)“指定”的動(dòng)作是在 Handler 內(nèi)部完成的,就是指定為 Handler 自己。
- Looper 將這個(gè)消息發(fā)送給 target 的 dispatchMessage 函數(shù)處理,因?yàn)?Handler 指定了 target 是自己,所以就是 Handler 的dispatchMessage 函數(shù)。
- dispatchMessage 函數(shù)對(duì)該消息進(jìn)行處理的時(shí)候,調(diào)用的是 handleMessage,就是由我們自己 override 的那個(gè)函數(shù)。
Reference
- http://weizhulin.blog.51cto.com/1556324/323922
- http://blog.csdn.net/Innost/article/details/6055793
-
轉(zhuǎn)載請(qǐng)注明來(lái)自“柳大·Poechant的CSDN博客”:blog.CSDN.net/Poechant