什么是Handler?
handler是android消息機制的上層接口 通過它可以將一個任務(wù)切換到handler所在的線程中去執(zhí)行
作用不僅僅是更新UI ?還可以做一些耗時的操作。
工作原理
Handler 創(chuàng)建時 會用當(dāng)前線程的looper來構(gòu)建內(nèi)部的消息循環(huán)系統(tǒng) handler創(chuàng)建完畢后looper和messageQueue就可以和handler一起協(xié)同工作了
handler 通過post方法將一個Runnable對象發(fā)送到handler內(nèi)部的looper中去處理 也可以通過handler的send方法發(fā)送消息 這個消息會在looper中去處理
其實post方法最終也是通過send方法來完成的
當(dāng)send方法被調(diào)用時會調(diào)用messageQueue的enqueueMessage方法將消息入列 looper發(fā)現(xiàn)了這個消息就會處理最終消息中的Runnable或者handler的handleMessage方法就會被調(diào)用
Looper是運行在創(chuàng)建handler所在的線程中的
handler
什么叫異步消息處理線程呢
異步消息處理線程啟動后會進入一個無限的循環(huán)體之中,每循環(huán)一次,從其內(nèi)部的消息隊列中取出一個消息,然后回調(diào)相應(yīng)的消息處理函數(shù),執(zhí)行完成一個消息后則繼續(xù)循環(huán)。若消息隊列為空,線程則會阻塞等待。
UI主線程初始化第一個Handler時會通過ThreadLocal創(chuàng)建一個Looper,
該Looper與UI主線程一一對應(yīng), Looper初始化的時候會創(chuàng)建一個消息隊列MessageQueue
Hander會持有對UI線程消息隊列MessageQueue和消息循環(huán)Looper的引用,
子線程可以通過Handler將消息發(fā)送到UI線程的消息隊列MessageQueue中
Looper主要是prepare()和loop()兩個方法。
prepare方法創(chuàng)建消息隊列 loop方法開始消息輪詢
Looper.prepareMainLooper();方法進行初始化Looper對象
子線程如何通過handler發(fā)送消息?
1.通過Handler的sendMessage方法將消息發(fā)送給消息隊列
2.給message貼上handler標簽;
開啟HandlerThread線程執(zhí)行run方法 調(diào)用looper.loop方法開啟消息循環(huán)
3.如果消息隊列中沒有這個消息則調(diào)用MessageQueue中的enqueueMessage(Message msg, long when)方法將消息入列
4.取出消息queue.next()分發(fā)消息msg.target.dispatchMessage(msg)
5.在ui線程的handMessage方法中處理消息
ThreadLocal
ThreadLocal ?是一個線程內(nèi)部的數(shù)據(jù)存儲類 它可在指定線程內(nèi)部存儲數(shù)據(jù) 也只能在指定線程中獲取數(shù)據(jù)
另一個使用場景是復(fù)雜邏輯下的數(shù)據(jù)傳遞 如監(jiān)聽器的傳遞
MessageQueue工作原理
主要包含兩個操作 插入和讀取 對應(yīng)方法 enqueueMessage和next
通過單鏈表的數(shù)據(jù)結(jié)構(gòu)維護消息列表
Looper工作原理
looper扮演消息循環(huán)的角色 ?構(gòu)造方法中創(chuàng)建了一個消息隊列
ActivityThread 主線程入口main ?系統(tǒng)通過 Looper.prepareMainLooper()來創(chuàng)建主線程 的 looper和messagaQueue 并通過looper.loop()來開啟主線程的消息循環(huán)
handler就 是ActivityThread.H
-------------請解釋下在單線程模型中Message,Handler,MessageQueue,Looper之間的關(guān)系。
拿主線程來說,主線程啟動時會調(diào)用Looper.prepare()方法,會初始化一個Looper,放入Threadlocal中,接著調(diào)用Looper.loop()不斷遍歷MessageQueue,
Handler的創(chuàng)建依賴與當(dāng)前線程中的Looper,如果當(dāng)前線程沒有Looper則必須調(diào)用Looper.prepare()。Handler? sendMessage到MessageQueue,Looper不斷從MessageQueue中取出消息,回調(diào)handleMessage方法。
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------