Handler机制

背景

我们都知道在Android开发中我们不能执行耗时操作在主线程,因为用户能感知到这个操作,并且UI的操作必须要在主线程中进行更新,那么我们如何传递子线程的信息通知给主线程进行UI更新呢?这时我们就需要用到Handler,进程间通信的方式。

Handler机制

pkRSW7t.png

Handler从子线程经过SendMessage()方法发送消息给Message Queue队列 Message队列给Looper传递,最后主线程通过检查Looper来得到Message。

为什么不能直接用子线程发给主线程?因为主线程不可能无时无刻的去直接查看我们的子线程是否发送了数据,我们可以通过Looper中转站来检测

具体过程:主线程初始化时已经有了Handler系统了。1. 子线程拿到主线程的Handler 2. 子线程调用SendMessage()方法向主线程发送消息 3. 主线程从消息队列中拿到消息,调用HandleMessage拿到消息。

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
private void updateBluetoothStatus(int state) {
new Thread(new Runnable() {
@Override
public void run() {
...
//1. 子线程执行完耗时操作后,触发更新蓝牙列表
if (mHandler != null) {
mHandler.removeMessages(H.MSG_XURUI_BLUETOOTH_LIST);
mHandler.sendEmptyMessage(H.MSG_XURUI_BLUETOOTH_LIST);
}
}
}).start();
}

private void updateBluetoothList() {
//3. 更新蓝牙列表
}
private static class H extends BaseHandler<BlueToothTestActivity> {
public static final int MSG_XURUI_BLUETOOTH_LIST = 100;
public H(BlueToothTestActivity activity) {
super(activity);
}

@Override
protected void handleMessage(BlueToothTestActivity activity, Message msg) {
if (msg.what == MSG_XURUI_BLUETOOTH_LIST) {
//2. 通过Handler机制调用updateBluetoothList
activity.updateBluetoothList();
}
}
}

Handler源码分析

一开始创建Handler会调用以下构造函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public Handler() {
this(null, false);
}

public Handler(Callback callback, boolean async) {
//1:获取Looper
mLooper = Looper.myLooper();
//如果获取不到Looper会提示我们要事先运行Looper.prepare()
if (mLooper == null) {
throw new RuntimeException(
"Can't create handler inside thread " + Thread.currentThread()
+ " that has not called Looper.prepare()");
}
//2:消息队列,来自Looper对象
mQueue = mLooper.mQueue;
mCallback = callback;
//设置消息为异步处理方式
mAsynchronous = async;
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();//1
}