Handler---4部曲---1. 总体流程
Handler---4部曲---2. ThreadLocal 存储主流程
Handler---4部曲---3. MessageQueue队列
Handler---4部曲---4.细节补充
为什么分4篇呢?
因为我在看别人的博客中发现,人集中注意力的时间是有限的, 看太长时间容易累, 无法集中注意力,Handler的内容还是有点东西的.
一 . ActivityThread中的main方法
public static void main(String[] args) {
Looper.prepareMainLooper();
Looper.loop();
}
总结: App启动, 执行2个方法.
1. Looper.prepareMainLooper()分析
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
//Looper.java
@Deprecated
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");
}
//创建Looper对象, 保存到sThreadLocal中
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
}
总结:
1. 创建Looper对象(每个线程只有一个), 保存到sThreadLocal中
2. 创建队列mQueue = new MessageQueue(...) , mQueue是Looper对象的成员变量
Looper.loop() 分析
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
public static void loop() {
// 1.从sThreadLocal中, 获取的Looper对象
Looper me = myLooper();
// 2.从Looper中, 获取队列
MessageQueue queue = me.mQueue;
for (;;) {
//循环取出消息
Message msg = queue.next();
//处理消息
msg.target.dispatchMessage(msg);
//释放资源
msg.recycleUnchecked();
}
}
总结:sThreadLocal--->取出当前线程Looper对象--->取出队列, 循环从队列取出消息处理
二. Handler发送消息
new Handler()
public Handler(xxx) {
mLooper = Looper.myLooper();
mQueue = mLooper.mQueue;
}
总结:从Looper中取出队列, Handler中的mQueue 就是 Looper中的队列
handler.post(xxx), handler.sendXxx(...)
public boolean sendMessageAtTime(@NonNull Message msg, long uptimeMillis) {
MessageQueue queue = mQueue;
enqueueMessage(queue, msg, uptimeMillis);
}
private boolean enqueueMessage(MessageQueue queue, Message msg,
long uptimeMillis) {
msg.target = this; //带着当前的Handler.
return queue.enqueueMessage(msg, uptimeMillis);
}
总结: msg携带当前的Handler对象, 加到队列中.
总体流程完结
细节1:Main函数,不允许再次初始化.
细节2:每个线程只允许prepare()初始化一次