創建流程:
主線程創建一個looper(只能有一個Looper),創建looper的同時,會在looper的內部創建一個消息隊列(MessageQueue)
創建Handler的時候,我們會取出當前線程的Looper,不斷的去輪詢MessageQueue中的Message。
整體流程:
Handler在子線程中發送的消息,實際上就是在MessageQueue中添加一條Message,通過Looper中的消息循環取得Message交給Handler處理。
源碼分析:
ThreadLocal概念:線程局部變量,是一種多線程間併發訪問變量的解決方案。與其synchronized等加鎖的方式不同,ThreadLocal完全不提供鎖,而使用以空間換時間的手段,爲每個線程提供變量的獨立副本,以保障線程安全。
從性能上說,ThreadLocal不具有絕對的優勢,在併發不是很高的時候,加鎖的性能會更好,但作爲一套與鎖完全無關的線程安全解決方案,在高併發量或者競爭激烈的場景,使用ThreadLocal可以在一定程度上減少鎖競爭。
通過ThreadLocal來創建線程的內部變量。只創建一個Looper
static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();
public static void prepare() {
prepare(true);
}
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));
}
Looper的構造方法,在創建Looper的時候,MessageQueue對象也被創建好了,這樣就能保證Looper中持有一個MessageQueue
private Looper(boolean quitAllowed) {
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
MessageQueue的數據結構其實並不是隊列,這裏採用了單鏈表的形式,因爲單鏈表在插入和刪除時,比隊列有優勢。
Handler創建的時候,會調用Looper.myLooper這個方法來得到Looper
mLooper = Looper.myLooper();
Looper.myLooper這個方法其實就是從ThreadLocal中得到Looper
public static @Nullable Looper myLooper() {
return sThreadLocal.get();
}
Handler處理消息
/**
* Handle system messages here.
*/
public void dispatchMessage(Message msg) {
if (msg.callback != null) {
handleCallback(msg);
} else {
if (mCallback != null) {
if (mCallback.handleMessage(msg)) {
return;
}
}
handleMessage(msg);
}
}
默認情況下,Android中新開啓的線程,是沒有開啓消息循環的,如果要在線程中使用Handler,那麼就要先調用Looper.prepare,主線程中,自動創建了Looper對象
Handler是Looper的一個接口,用來想Looper的MessageQueue中發送Message
在非UI線程中,直接new Handler()是不可以的,因爲Handler需要發送消息到MessageQueue,而你所在的線程中沒有MessageQueue,所以必須要先創建Looper對象。
Android中爲什麼主線程不會因爲Looper.loop()裏的死循環卡死?
https://www.zhihu.com/question/34652589