Handler 機制---學(xué)習(xí)筆記

handler機制的原理 - 劉望舒的專欄 - 博客頻道?

什么是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方法。

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容