PS:剛剛都快寫完了,竟然提示編輯器掛了,再進來啥都木有了,坑啊,坑啊,啊
我們在一個子線程中創建Handler的實例,如下所示
PRivate Handler mHandler; private class LooperThread extends Thread{ @Override public void run() { super.run(); mHandler = new Handler(); }}在運行的時候會報錯”Can’t create handler inside thread that has not called Looper.prepare()”,根據字面意思很清楚的可以看出是因為我們沒有調用Looper.prepare()方法導致的。我通過Looper.prepare()方法的源碼去分析消息機制的內部是怎樣的原理,以及Looper類在消息機制中承擔了何種角色。 首先我們查看Looper.prepare()方法的源碼。
結合這兩段代碼可以看出Looper.prepare()方法的作用就是創建一個Looper的實例并且將其放入到ThreadLocal中去,我們知道ThreadLocal可以保證不同線程間的數據互不干涉,在通過new Looper()可以看出Looper的實例化過程就是創建一個消息隊列,和獲取當前的子線程,將其放入到ThreadLocal中去,所以我們可以看出Looper、Queue、Thread是一一對應,每個子線程之間互不干涉。 在調用Looper.prepare()之后new Handler()正常,通過源碼可以看到
Handler實例會將對應的ThreadLocal中的Looper取出,通過Looper來管理監聽消息隊列。在Looper.prepare()方法源碼的注釋中可以看到,Looper.loop()方法是開始輪詢消息隊列。
調用Looper.loop()后會阻塞子線程輪詢消息隊列。調用Looper.quit()結束輪詢。 綜上,Looper、線程、隊列是一一對應的,不同的子線程存在不同的Looper在ThreadLocal中互不影響。值得注意的是,主線程自動創建Looper,而子線程需要手動創建。所以官方寫法為: 
消息的處理過程分為:入隊、出隊、處理。 消息入隊的過程實質上就是發送消息的過程,Handler發送消息方法: post()、postAtTime()、postDelayed()、postAtFrontOfQueue(); 通過源碼我們可以看到前三種方式都會調用到
正常來講,消息的入隊過程就相當于銀行區號排隊,我們從1號開始發送號碼然后遞增,來的越早號碼越小越先出隊,這里參數”uptimeMillis”就相當于號碼牌。 我們再看postAtFrontOfQueue()方法的源碼
可以看出其實它的原理和前三個方法是一樣的,不過是參數”uptimeMillis”被置為常量0,這就相當于銀行大家都是排隊時突然過來一個Vip金卡用戶,隊列會把這條消息排在隊伍最前面優先出隊(銀行優先處理)。
Thread:線程負責業務邏輯。 Handler:消息的發送和處理。 消息隊列:保存消息。 Looper:輪詢消息。 
新聞熱點
疑難解答