一、Handler机制
创建一个Handler
//提示已过时
Handler handler = new Handler();
Handler handler = new Handler(Looper.myLooper());
隐式指定Looper
的Handler
初始化方法已被Android 11报过时,根据注释,是由于不指定Looper
在一些场景下会导致任务丢失或程序崩溃,比如没有Looper
的线程。
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
下面寻找这个Looper
是在哪里初始化的
在ActivityThread.java#main
中
public static void main(String[] args) {
...
Looper.prepareMainLooper();
...
Looper.loop();
}
Looper.java
public static void prepareMainLooper() {
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
sThreadLocal.set(new Looper(quitAllowed));
}
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
根据ThreadLocal
原理,调用Looper.prepare(boolean quitAllowed)
时将该<ThreadLocal<Looper>,Looper>
键值对设置到了当前线程的成员变量ThreadLocal.ThreadLocalMap threadLocals
中,从而保证了每个线程对应唯一一个Looper
,且不能被重复初始化,否则将抛出异常。而且Looper
对象在初始化时也初始化了MessageQueue
,并将当前线程保存在成员变量中。
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
以上初步实现了主线程对应sMainLooper
,同时对应唯一一个MessageQueue
。
下面分析Looper
、MessageQueue
、Handler
如何运转起来
public static void loop() {
final Looper me = myLooper();
...
final MessageQueue queue = me.mQueue;
...
//死循环
for (;;) {
Message msg = queue.next();
...
try {
//将消息分发给相应Handler处理
msg.target.dispatchMessage(msg);
...
}
}
...
}
下面看Handler
处理消息的过程
从sendMessage()
、postDelayed()
、post()
都会调用到enqueueMessage
private boolean enqueueMessage(@NonNull MessageQueue queue, @NonNull Message msg,
long uptimeMillis) {
msg.target = this;
msg.workSourceUid = ThreadLocalWorkSource.getUid();
if (mAsynchronous) {
msg.setAsynchronous(true);
}
return queue.enqueueMessage(msg, uptimeMillis);
}
下面看MessageQueue#enqueueMessage
:
boolean enqueueMessage(Message msg, long when) {
...
synchronized (this) {
...
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 {
...
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;
}
...//唤醒线程本地方法
}
}
可以看到,消息入队时加了锁,保证了多个Handler
向MessageQueue
添加数据时的线程安全。添加消息首先判断队列中是否有消息,没有消息的时候需要对线程进行唤醒。如果不需要唤醒,则按照延迟时间入队。至于时间的判定,来自于Handler#sendMessageDelayed