最詳細(xì)的講解:
http://www.lxweimin.com/p/e172a2d58905
http://www.lxweimin.com/p/b4d745c7ff7a
handler機(jī)制涉及到的類有Looper,Handler,MessageQueue和Message。
一句話概括,Looper不斷獲取MessageQueue中的Message,交給Handler處理,同時(shí)Handler還向MessageQueue中投遞Message。
1.Handler
首先Handler與線程Thread是一對(duì)多的關(guān)系,因?yàn)槊總€(gè)Thread只對(duì)應(yīng)一個(gè)Looper,每個(gè)Looper只對(duì)應(yīng)一個(gè)MessageQueue,每個(gè)MQ中有多個(gè)Message,每個(gè)Message最多指定一個(gè)Handler處理。Handler有兩個(gè)作用,一是處理Message,二是將某個(gè)Message壓入MQ中。
實(shí)現(xiàn)第一個(gè)作用的方法是dispatchMessage和handleMessage. Looper從MQ中取出一個(gè)Message后,先調(diào)用Handler.dispatchMessage進(jìn)行分發(fā),流程是如果Message.callback不是空,執(zhí)行該callback;如果Handler.callback不是空,執(zhí)行該callback;如果前面的callback都不存在,調(diào)用Handler.handleMessage.
實(shí)現(xiàn)第二個(gè)作用的方法是send系列方法和post系列方法. send系列需要的參數(shù)是一個(gè)Message,post需要的參數(shù)是Runnable,本質(zhì)上是把Runnable設(shè)置為一個(gè)Message的callback,再壓入MQ。
2.MessageQueue
MessageQueue是一個(gè)隊(duì)列,有入隊(duì)出隊(duì),新增和銷毀等方法。
3.Looper
程序中的Looper有兩種情況,主線程的Looper和普通線程的Looper。它的使用都有3個(gè)步驟:1.Looper.prepare;2.創(chuàng)建處理消息的Handler;3.Looper.loop() .
prepare方法中會(huì)在當(dāng)前線程的ThreadLocal中保存一份Looper。ThreadLocal是一種線程內(nèi)的全局變量,不同線程中的ThreadLocal相互獨(dú)立無(wú)法訪問。Handler的構(gòu)造方法會(huì)獲取當(dāng)前線程的Looper,同時(shí)保存Looper的MQ
這樣四個(gè)對(duì)象就串起來(lái)了
其他知識(shí)點(diǎn)
https://www.cnblogs.com/muouren/p/11706454.html
https://blog.csdn.net/asdgbc/article/details/79148180
Handler 同步屏障 和 異步消息
Handler中的Message可以分為兩類:同步消息、異步消息,一般情況下這兩種消息的處理方式?jīng)]什么區(qū)別,只有在設(shè)置了同步屏障時(shí)才會(huì)出現(xiàn)差異。
從代碼層面上來(lái)講,同步屏障就是一個(gè)Message,一個(gè)target字段為空的Message。
設(shè)置了同步屏障之后,Handler只會(huì)處理異步消息。再換句話說(shuō),同步屏障為Handler消息機(jī)制增加了一種簡(jiǎn)單的優(yōu)先級(jí)機(jī)制,異步消息的優(yōu)先級(jí)要高于同步消息。如何使用異步消息?
異步消息是不能使用的,因?yàn)橄嚓P(guān)設(shè)置都是hide。
handler的相關(guān)構(gòu)造函數(shù),hide
Mesasge.setAsynchronous(boolean),hide
IdleHandler
SyncBarrier(同步障礙器)與IdleHandler(閑時(shí)任務(wù))機(jī)制都是通過(guò) MQ 的 next() 方法提供的,
執(zhí)行IdleHandler其實(shí)就是調(diào)用其queueIdle()方法,queueIdle()如果返回false,next()方法會(huì)將該IdleHandler從mIdleHandlers中刪除。這樣的話,下一次next()方法再執(zhí)行IdleHandler時(shí)就不會(huì)再重復(fù)執(zhí)行它了。
Looper.prepare() 做了什么事情
new 一個(gè) Looper,然后保存在 ThreadLocal 中,和當(dāng)前線程綁定