Handler 概要
官方文档
Handler 可以发送、处理 Message 和与线程关联的 Runnable 对象 MessageQueue ,每个 Handler 实例都与一个线程和该线程的消息队列关联。创建新的 Handler 时会绑定到 Looper。它将消息和线程传递到该 Looper 的消息队列,并在该 Looper 的线程上执行它们
Handler 两个主要用途:在将来某个时刻执行消息和线程。在不同线程(切换线程)按顺序执行操作
发送方法有 post(Runnable) , postDelayed(Runnable, long), sendMessage(Message) 等
默认通过 handleMessage(Message) 处理接收 Message
Handler、Message、MessageQueue以及Looper
- Handler 负责发送和处理消息(Handler发送消息给 MessageQueue 和接收 Looper 返回的消息并且处理消息)
- Message 用来携带需要的数据
- MessageQueue 消息队列(实际用链表实现的),负责存放 Handler 发送过来 Message
- Looper 负责不停的从 MessageQueue 中取 Message 交给 Handler 处理
Handler 通过 sendMessage 发送 Message 到 MessageQueue 队列,Looper 通过 loop() 从 MessageQueue 取出 Message,再经过 msg.target.dispatchMessage 交给 Handler 的 handleMessage() 进行处理
发送消息
发送消息最后都是调用到 sendMessageAtTime ,sendMessageAtTime 最后返回 enqueueMessage 方法
enqueueMessage(queue, msg, uptimeMillis) 中将调用发送消息的 Handler 与 Message 进行绑定
MessageQueue 中的 enqueueMessage 将 Message 放入 MessageQueue
成功放入消息队列返回 true 。处理消息队列正在退出则失败,返回 false
Handler中部分发送消息代码如下
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
| public final boolean post(@NonNull Runnable r) {
return sendMessageDelayed(getPostMessage(r), 0);
}
public final boolean postDelayed(@NonNull Runnable r, long delayMillis) {
return sendMessageDelayed(getPostMessage(r), delayMillis);
}
public final boolean sendMessage(@NonNull Message msg) {
return sendMessageDelayed(msg, 0);
}
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
if (queue == null) {
RuntimeException e = new RuntimeException(
this + " sendMessageAtTime() called with no mQueue");
Log.w("Looper", e.getMessage(), e);
return false;
}
return enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
//将调用发送消息的Handler与Message进行绑定
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
|
MessageQueue 中的 enqueueMessage
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
| boolean enqueueMessage(Message msg, long when) {
if (msg.target == null) {
throw new IllegalArgumentException("Message must have a target.");
}
if (msg.isInUse()) {
throw new IllegalStateException(msg + " This message is already in use.");
}
synchronized (this) {
if (mQuitting) {
IllegalStateException e = new IllegalStateException(
msg.target + " sending message to a Handler on a dead thread");
Log.w(TAG, e.getMessage(), e);
msg.recycle();
return false;
}
msg.markInUse();
msg.when = when;
Message p = mMessages;
boolean needWake;
if (p == null || when == 0 || when < p.when) {
// New head, wake up the event queue if blocked.
msg.next = p;
mMessages = msg;
needWake = mBlocked;
} else {
// Inserted within the middle of the queue. Usually we don't have to wake
// up the event queue unless there is a barrier at the head of the queue
// and the message is the earliest asynchronous message in the queue.
needWake = mBlocked && p.target == null && msg.isAsynchronous();
Message prev;
for (;;) {
prev = p;
p = p.next;
if (p == null || when < p.when) {
break;
}
if (needWake && p.isAsynchronous()) {
needWake = false;
}
}
msg.next = p; // invariant: p == prev.next
prev.next = msg;
}
// We can assume mPtr != 0 because mQuitting is false.
if (needWake) {
nativeWake(mPtr);
}
}
return true;
}
|
处理消息
Looper.loop() 方法中通过死循环调用 queue.next() 取出消息使用 dispatchMessage(msg) 处理将要执行的消息
优先级 Message 的 callback > Handler 的 mCallback > Handler 的 handleMessage
使用 Handler 的 sendMessage 方法,最后在 handleMessage(Message msg) 方法中来处理消息。
使用 Handler 的 post 方法,最后在 Runnable 的 run 方法中来处理,
Looper.loop()部分代码:
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
| public static void loop() {
//通过myLooper方法拿到与线程绑定(执行了Looper.prepare方法的线程)的Looper
final Looper me = myLooper();
if (me == null) {
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
//从Looper中得到MessageQueue
final MessageQueue queue = me.mQueue;
...
//死循环
for (;;) {
//从消息队列中不断取出消息
Message msg = queue.next(); // might block
if (msg == null) {
// No message indicates that the message queue is quitting.
return;
}
...
try {
//处理消息
msg.target.dispatchMessage(msg);
if (observer != null) {
observer.messageDispatched(token, msg);
}
dispatchEnd = needEndTime ? SystemClock.uptimeMillis() : 0;
} catch (Exception exception) {
if (observer != null) {
observer.dispatchingThrewException(token, msg, exception);
}
throw exception;
} finally {
ThreadLocalWorkSource.restore(origWorkSource);
if (traceTag != 0) {
Trace.traceEnd(traceTag);
}
}
...
msg.recycleUnchecked();
}
}
|
Handler中的dispatchMessage方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| public void dispatchMessage(@NonNull Message msg) {
//msg.callback 就是 Runnable 对象
if (msg.callback != null) {
handleCallback(msg);
} else {
//向 Hanlder 的构造函数传入一个 Handler.Callback 对象,并实现 Handler.Callback 的 handleMessage 方法
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
//无需向 Hanlder 的构造函数传入 Handler.Callback 对象,但是需要重写 Handler 本身的 handleMessage 方法
handleMessage(msg);
}
}
|
ThreadLocal
线程内部的数据存储类,通过它存储的数据只有在它自己的线程才能获取到,其他线程是获取不到的
Handler 主要利用了 ThreadLocal 在每个线程单独存储副本的特性
其他
Looper 相关
Looper.prepare 方法的作用就是将实例化的Looper与当前的线程进行绑定
在子线程中使用 Handler 要调用Looper.prepare() , Looper.loop() ,主线程不用写,是因为 framework 层的 Android 的主线程 ActivityThread 类调用了 Looper.prepareMainLooer()
创建 Handler 的代码需要放在 Looper.prepare(); & Looper.loop();中间执行,这是因为创建 Handler 对象时需要聚合 Looper 对象(默认使用的是当前线程的 Looper),而只有执行 Looper.prepare();之后,才会创建该线程私有的 Looper 对象,否则创建 Handler 会抛异常
每个线程只允许调用一次 Looper.prepare()
由于多个线程之间共享内存空间,所以 Handler 可以在线程A把消息存放到 MessageQueue,Looper 可以在线程B把消息取出来,一存一取之间就实现了线程的切换
ANR
ANR 是 Android 中的一种机制,它是在应用没有按时完成 AMS 指定的任务才触发的。组件在创建时会向 AMS 申请开始计时,当完成创建后会通知 AMS 取消计时
涉及到 Linux pipe/epoll 机制,简单说就是在主线程的 MessageQueue 没有消息时,便阻塞(epoll.wait)在 loop 的 queue .next() 中的 nativePollOnce() 方法里,此时主线程会释放 CPU 资源进入休眠状态,直到下个消息到达或者有事务发生,通过往 pipe 管道写端写入数据来唤醒主线程工作
一直死循环不会造成 cpu 浪费么
在没有消息的时候,会阻塞在 nativePollOnce 方法上,让出 cpu 资源,进入休眠状态,当有新的任务进入时会重新唤醒 cpu
同步屏障
同步屏障(SyncBarrier)是 Handler 用来筛选高低优先级消息的机制,即:当开启同步屏障时,高优先级的异步消息优先处理。
平时要发送同步屏障postSyncBarrier需要反射才能使用
在 android 中 为了更快响应 UI 刷新 choreographer 使用到了