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()初始化一次