1 Overview
先浅析本质太过抽象,还是先上 Handler 的最简实例吧。
- 功能:
Android.os.Handler
负责接收,并按计划发送和处理消息; - 特点:处理消息是阻塞式的;
- 本质:关于
Handler
的内部机制,及其与Looper
的关系,请看本文的第三部分“消息处理机制的本质”。
2 Get Started
2.1 先创建一个 Handler 对象,
private Handler mHandler = new Handler();
但这样的Handler
是没用的。不过先暂且不要管,往下面看。
2.2 向 Handler 的消息队列发送数据
发送数据的动作是通过 sendMessage 完成的。
Message message = new Message();
message.what = 1;
// 将消息发送到mHandler的消息队列的最后
mHandler.sendMessage(message);
不过实际上,在 Handler 内部有一个 Looper 类,而消息队列其实是 Looper 的一个成员。Handler 中的 mQueue 就是其成员 mLooper 的 mQueue。
2.3 处理消息队列中的数据
Handler 可以根据 Message 中的 what 值的不同来分发处理,Handler 中提供了 handleMessage 来让开发人员进行 Override。示例如下:
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 所做的操作
break;
case 2:
// 所做的操作
break;
default:
// 所做的操作
}
};
完整的写法,就是在创建 Handler 对象时如下:
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 所做的操作
break;
case 2:
// 所做的操作
break;
default:
// 所做的操作
}
};
}
2 计时器简例
2.1 先创建一个任务类
Timer 和 TimerTask 是 Java 语言中的类,如果不熟悉,请看下面的例子及注视。
// 任务类
private class MyTask extends TimerTask{
@Override
public void run() {
// 创建要发送的消息
Message message = new Message();
message.what = 1;
// 将消息发送到mHandler的消息队列的最后
mHandler.sendMessage(message);
}
}
使用方法很简单,就是用 Timer 来作为容器:
// 创建用于执行任务类的Timer
Timer timer = new Timer();
// 1毫秒之后开始每隔5秒钟执行一次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方法提供变量,这里为了方便我设置成了int型
private int mSecs = 0;
private Handler mHandler = new Handler(){
// 根据mHandler的消息队列中的不同消息进行处理
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
// 所做的操作
updateTitle();
break;
}
};
};
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建用于执行任务类的Timer
Timer timer = new Timer();
// 1毫秒之后开始每隔5秒钟执行一次MyTast
timer.scheduleAtFixedRate(new MyTask(), 1, 1000);
}
// 任务类
private class MyTask extends TimerTask{
@Override
public void run() {
// 创建要发送的消息
Message message = new Message();
message.what = 1;
// 将消息发送到mHandler的消息队列的最后
mHandler.sendMessage(message);
}
}
// 处理消息所做的操作
public void updateTitle(){
setTitle("Michael's Timer: " + mSecs);
mSecs++;
}
}
3 消息处理机制的本质
3.1 Looper 与 Handler 的内部机制
Looper 中有一个 MessageQueue 的成员,Looper 中还有有一个 loop 函数用来对消息队列进行循环。Looper 并不直接与 Handler 绑定,我们可以直接“玩弄” Looper,不过 Handler 让我们“玩弄”她更容易一些。
Handler 本质上是一个工具类,其内部有 Looper 成员。我们通过 Handler 类完成消息的发送和处理、制定分发机制等等。
3.2 消息处理机制的本质
Handler 中封装了 Looper 成员,Handler 中的消息队列就是 Looper 中的消息队列成员。Looper 中有消息的循环分发机制。下面介绍下内部的大致流程:
- 当将一个消息通过 sendMessage 交给 Handler 的时候,就是交给了 Looper;
- Looper 将消息发送到这个消息指定的 target,而这个“指定”的动作是在 Handler 内部完成的,就是指定为 Handler 自己。
- Looper 将这个消息发送给 target 的 dispatchMessage 函数处理,因为 Handler 指定了 target 是自己,所以就是 Handler 的dispatchMessage 函数。
- dispatchMessage 函数对该消息进行处理的时候,调用的是 handleMessage,就是由我们自己 override 的那个函数。