Handler源碼解析-有關Handler那些事

   Handler被成爲異步處理大師,相信大家都會用,面試中也經常會問到Handler的底層原理。今天就來看一看Handler的機制。

    Android的消息處理有四個核心類:Handler、Looper、Message、MessageQueue,都在android.os包中。
Looper的字面意思是“循環器”,"輪詢器",它被設計用來使一個普通線程變成Looper線程。所謂Looper線程就是循環工作的線程。在程序開發中(尤其是GUI開發中),經常會需要一個線程不斷循環,一旦有新任務則執行,執行完繼續等待下一個任務,這就是Looper線程。
什麼是handler?handler扮演了往MQ上添加消息和處理消息的角色(只處理由自己發出的消息),即通知MQ它要執行一個任務(sendMessage),並在loop到自己的時候執行該任務(handleMessage),整個過程是異步的。handler創建時會關聯一個looper,默認的構造方法將關聯當前線程的looper。



來看看Handler的官方註釋:


一個Handler可以讓你用來發送和處理消息(Message),以及消息上附帶的Runnable對象,整個是跟消息隊列(MessageQueue)一起使用的。每一個Handler實例會關聯到一個唯一的線程和該線程的MessageQueue。如果你創建了一個Handler,他將會跟創建這個Handler的線程和該線程的消息隊列綁定在一起。也就是說通過把消息發往這個隊列和在出列的時候處理他們。Handler一般有兩種應用產景,(1)就是調度消息和runnable對象在未來的某個時間點執行(歸納起來就是消息的發送);(2)可以把消息發送到其他線程裏面。再簡單概括一下就是Handler是跟創建他的線程綁定在一起的,然後通過消息隊列方式,實現線程安全的操作。


Handler的創建


當我們調用send(),post()方法時,其實是執行了這個:



第一句把msg.target設置爲當前的handler本身,這一步很重要,因爲在這之後,就跟handler沒關係了,後面會分析;接着就調用消息隊列的入列方法把消息體丟到隊列裏面排隊等待執行。

可以看到,不管是什麼方式,最終都是把消息(runnable最後也是包裝成消息)丟到消息隊列裏面。


接着是Looper的工作機制


這其實就是一個生產者消費者的模型,在for循環裏面,looper不斷的訂閱消息隊列的下一個元素(next()方法),然後調用Handler的dispatchMessage方式分發消息給handler進行處理。這裏消息一個一個處理完之後纔會處理下一個,是單線程串行執行的,而且跟創建handler的線程是同一個線程,所以完美的避免的線程安全的問題。那麼你的疑問會是,究竟是誰來調用這個loop方法的,不是會卡住嗎?是的,這就是精髓所在,這裏的looper是UI線程在初始化完所有的UI操作之後調用的,這樣一來,就不會有卡住的問題了。


這裏是消息分發的操作:


handleMessage方法是優先級最低的,因爲有Handler有個post方法。參數是一個Runnable對象,然後通過創建一個Message,再把message的callback設置爲這個runnable,然後再發送到消息隊列裏面。post方法的場景是你更新UI的時候需要知道獲取到了什麼新的數據,然後直接更新。而handleMessage方法可以不需要知道更新了哪些數據,就僅僅更新UI就可以了。

handler之所以可以更新UI,不是系統做了什麼神奇般的兼容,而是因爲他跟UI線程使用的本來就是同一個線程,UI線程通過Looper.loop來等待消息的分發,handler發送消息後把消息放到消息隊列裏面,而Looper負責從消息隊列裏面拿數據,又交給handler進行處理,最終實現了UI的異步更新操作。這是個生產者消費者模型典型應用,其中消息隊列的功勞巨大,我們來看看他有哪些功能。如果我們開發中也需要實現這種類似的生產者消費者模型,可以使用這一套機制。需要注意的是,MessageQueue我們不能單獨定義來使用,因爲其核心API的可訪問修飾符都是包級別的,我們不能把代碼定義到android.os這個包下面,所以他要通過配合Looper來使用。Looper的核心API都是開放的。


enqueueMessage入列,可以把消息放到隊列裏面,這裏隊列的底層是android的本地代碼實現的,其實可以參照juc裏面的DelayQueue的實現,機制差不多,都支持延時出列的,這不過實現方式不同罷了。

next()出列,消息出列,隊列的出列優先級是入列的時候定義的時間來決定的,時間值越小(長整形)優先級越高。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章