第九周总结
时间:2019 年 02 月 25 日 ~ 2019 年 03 月 01 日
一、Handler
Handler 消息机制
Handler 消息机制除了 Handler 本身外,还包含:Looper、MessageQueue、Message,消息机制需要有消息队列、消息循环、消息处理
如下:
Handler:发送消息(Message)到消息队列(MessageQueue)
Looper:遍历消息队列(MessageQueue)中的消息(Message),然后分发给对应的 Handler(谁发送的消息谁处理)
MessageQueue:消息队列,存储消息
Message:消息本身
Handler 消息机制工作流程简图:
在子线程中使用 Handler 的栗子
class MyThread extends Thread {
public Handler handler;
@Override
public void run () {
Looper.prepare();
Handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 处理消息
}
};
Looper.loop();
}
}
使用 Handler 之前,需要调用 Looper#prepare()?
public static void loop() {
// 获取 Loop 对象
final Looper me = myLooper();
// Looper 对象为空
if (me == null) {
// 抛异常
throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
}
...
}
消息要经过 Looper#loop() 方法的遍历,然后才能分发给对应的 Handler 去处理,在 loop() 方法的最开始对 Loop 对象是否为空进行了判断
Loop#myLooper():
// sThreadLocal.get() will return null unless you've called prepare().
// 根据泛型可知,sThreadLocal 中存储的是 Looper
// 根据源码注释可知,直到调用了 prepare() 方法,sThreadLocal.get() 返回值才不为空
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static @Nullable Looper myLooper() {
// 由上面的 sThreadLocal 可知,需要调用 prepare() 方法,sThreadLocal.get() 返回值才不为空
return sThreadLocal.get();
}
Loop#prepare():
public static void prepare() {
prepare(true);
}
private static void prepare(boolean quitAllowed) {
// 一个线程只能创建一个 Loop
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 创建 Looper 对象实例,保存到 sThreadLocal 变量中
sThreadLocal.set(new Looper(quitAllowed));
}