为了更好的理解Handler的工作原理,先介绍一下与Handler一起工作的几个组件。
-
Message: Handler接收和处理的消息对象
-
Looper:每个线程只能拥有一个Looper。它的loop方法负责读取MessageQueue中的消息,之后把消息交给发送该消息的Handler处理
-
MessageQueue:消息队列,使用先进先出的方式来管理Message。程序创建Looper对象时会在它的构造器中创建MessageQueue对象。下面是Looper的构造函数:
1
2
3
4
5
|
private
Looper() {
mQueue =
new
MessageQueue();
//这里创建MessageQueue,这个Queue就负责管理消息
mRun =
true
;
mThread = Thread.currentThread();
}
|
-
Handler,它的作用有两个——发送消息和处理消息。程序使用Handler发送消息,被Handler发送的消息必须被送到指定的MessageQueue。也就是说,如果希望Handler正常工作,必须在当前线程中有一个MessageQueue,否则消息就没地方保存了。而MessageQueue是由Looper管理的,因此必须在当前线程中有一个Looper对象,可以分如下两种情况处理:
-
主UI线程中,系统已经初始化了一个Looper对象,因此程序直接创建Handler即可,然后就可以通过Handler来发送消息和处理消息了。
-
程序员自己启动的子线程中,必须自己创建一个Looper对象,并启动它。调用它的prepare()方法即可创建Looper对象。
prepare()方法保证每个线程最多只有一个Looper对象:
1
2
3
4
5
6
|
public
static
final
void
prepare() {
if
(sThreadLocal.get() !=
null
) {
throw
new
RuntimeException(
"Only one Looper may be created per thread"
);
}
sThreadLocal.set(
new
Looper());
//这里创建Looper对象并放到ThreadLocal中
}
|
然后调用Looper的静态loop()方法来启动它。loop()方法使用一个死循环不断取出MessageQueue中的消息,并将其分发给对应的Handler进行处理:
1
2
3
4
5
6
7
8
9
10
|
for
(;;) {
Message msg = queue.next();
//获取Queue中的下一个消息,如果没有,将会阻塞
if
(msg ==
null
) {
//如果消息为null,表明MessageQueue正在退出
return
;
}
...
msg.target.dispatchMessage(msg);
...
}
|
在线程中使用Handler的步骤如下:
-
调用Looper.prepare()为当前线程创建Looper对象,这将自动创建与之配套的MessageQueue
-
创建Handler子类的实例,重写handleMessage(Message msg)分发,该方法负责处理来自其他线程的消息
-
调用Looper.loop()启动Looper
例:输入一个整数,单击“计算”按钮,计算小于这个整数的所有质数。Activity的代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
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();
//Step1.创建Looper对象
mHandler =
new
Handler() {
//Step2.创建Handler对象
//重写处理Message的方法
@Override
public
void
handleMessage(Message msg) {
if
(msg.what ==
123
) {
int
upper = msg.getData().getInt(UPPER_NUM);
List<Integer> nums =
new
ArrayList<Integer>();
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.makeText(CalPrime.
this
, nums.toString(), Toast.LENGTH_LONG).show();
}
}
};
Looper.loop();
//Step3.启动Looper
}
}
@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);
}
}
|