Android Handler 機(jī)制實(shí)現(xiàn)原理分析
handler在安卓開發(fā)中是必須掌握的技術(shù),但是很多人都是停留在使用階段。使用起來很簡(jiǎn)單,就兩個(gè)步驟,在主線程重寫handler的handleMessage( )方法,在工作線程發(fā)送消息。但是,有沒有人想過這種技術(shù)是怎么實(shí)現(xiàn)的呢?下面我們一起探討下。
先上圖,讓大家好理解下handler機(jī)制:
handler機(jī)制示例圖
上面一共出現(xiàn)了幾種類,ActivityThread,Handler,MessageQueue,Looper,msg(Message),對(duì)這些類作簡(jiǎn)要介紹:
ActivityThread:程序的啟動(dòng)入口,為什么要介紹這個(gè)類,是因?yàn)樵擃惥褪俏覀冋f的主線程,它對(duì)Looper進(jìn)行操作的。
Handler:字面意思是操控者,該類有比較重要的地方,就是通過handler來發(fā)送消息(sendMessage)到MessageQueue和 操作控件的更新(handleMessage)。handler下面持有這MessageQueue和Looper的對(duì)象。
MessageQueue:字面意思是消息隊(duì)列,就是封裝Message類。對(duì)Message進(jìn)行插入和取出操作。
Message:這個(gè)類是封裝消息體并被發(fā)送到MessageQueue中的,給類是通過鏈表實(shí)現(xiàn)的,其好處方便MessageQueue的插入和取出操作。還有一些字段是(int what,Object obj,int arg1,int arg2)。what是用戶定義的消息和代碼,以便接收者(handler)知道這個(gè)是關(guān)于什么的。obj是用來傳輸任意對(duì)象的,arg1和arg2是用來傳遞一些簡(jiǎn)單的整數(shù)類型的。
下面,我們按照啟動(dòng)順序來進(jìn)行源碼分析:
從上面可以看出,ActivityThread類是用來啟動(dòng)Android的,其源碼為:
ActivityThread類:
接下來,我們看到Looper類了,我們進(jìn)去看看里面的源碼實(shí)現(xiàn):
首先,我們看看里面有哪些字段:
Looper的內(nèi)部屬性
然后我們迫不及待地要想去看看prepareMainLooper方法,到底干了什么
Looper.prepareMainLooper()方法
這里我們可以看到,prepareMainLooper是為了設(shè)置一個(gè)持有消息隊(duì)列和消息序列器的Looper進(jìn)去ThreadLocal。接下來我們看看loop方法吧:
Looper.loop()方法
我們可以看到loop方法中,會(huì)取出內(nèi)部的消息序列器,并且迭代里面的消息,根據(jù)消息的target分發(fā)消息(到handleMessage方法中)。如果你有疑問,你應(yīng)該是不清楚Looper的MessageQueue為什么會(huì)有Message。那么我們就馬上去看,到底是哪里添加消息的。話說,到了這里我也好像沒有分析到和我們handler相關(guān)的操作吧。因?yàn)槟愫臀叶贾纇andler的作用是sendMessage和handleMessage,所以我們知道,Looper中的消息序列器的消息體,肯定是從sendMessage中添加進(jìn)去的。不墨跡,我們馬上進(jìn)入Handler的源碼分析。
首先,我們先看看Handler的字段:
Handler的字段
接著,我們看看Handler的構(gòu)造方法,我們可以看到,Handler有兩類構(gòu)造方法(別看到6個(gè),它們都是往這兩種方法調(diào)用的):
Handler的構(gòu)造方法
接著,我們要進(jìn)入Handler.dispatchMessage()方法,因?yàn)槲覀円忉屔厦鎰倓侺ooper.loop方法。dispatchMessage的方法很簡(jiǎn)單,只有三個(gè)方向,其源碼為:
Handler.dispatchMessage()方法
到這里為止,執(zhí)行代碼就結(jié)束了。那么問題來了,消息從哪里來的?帶著這個(gè)疑問,我們馬上進(jìn)入Handler.sendMessage()邏輯去看看,其源碼是:
Handler.sendMessage()方法
好不容易找到了發(fā)送消息的邏輯并理解了,但是還要去殼,在MessageQueue中分析了,首先,我們回顧下,消息序列器是在Looper.prepare()中初始化的。MessageQueue源碼,構(gòu)造方法很簡(jiǎn)單:
MessageQueue構(gòu)造方法
然后我們?cè)俚竭_(dá)MessageQueue.enqueueMessage()方法中看源碼:
MessageQueue.enqueueMessage()方法
這個(gè)是發(fā)送消息的最終執(zhí)行代碼,就是把消息放進(jìn)消息序列器。在Looper.loop()方法中,我們是需要不斷從消息序列器中取出消息的。其過程也是我們可以進(jìn)去MessageQueue.next()的源碼中看看:
MessageQueue.next()方法
這樣,整個(gè)過程就完成了。在這些執(zhí)行過程中,Message是它們的物件。我們可以看看Message的結(jié)構(gòu):
Message的字段
除此之外,Message的數(shù)據(jù)結(jié)構(gòu)是基于鏈表的,方法都很簡(jiǎn)單的,我就不貼出來了。
總結(jié)一下,其實(shí)就是用一個(gè)ThreadLocal來存儲(chǔ)對(duì)象,然后在執(zhí)行的時(shí)候,能夠保證對(duì)象的不變形,這樣就能達(dá)到在主先線程更新UI了。
以上就是對(duì)Android Handler 進(jìn)行的詳解,后續(xù)繼續(xù)整理相關(guān)資料,謝謝大家對(duì)本站的支持!
相關(guān)文章
Android計(jì)步功能的實(shí)現(xiàn)代碼
本篇文章主要介紹了Android計(jì)步功能的實(shí)現(xiàn)代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-03-03Android開發(fā):微信授權(quán)登錄與微信分享完全解析
本篇文章主要介紹了Android微信授權(quán)登錄與微信分享,具有一定的參考價(jià)值,有需要的可以了解一下。2016-11-11Android中實(shí)現(xiàn)OkHttp上傳文件到服務(wù)器并帶進(jìn)度
本篇文章主要介紹了Android中實(shí)現(xiàn)OkHttp上傳文件到服務(wù)器并帶進(jìn)度,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07Android Retrofit的簡(jiǎn)單介紹和使用
這篇文章主要介紹了Android Retrofit的簡(jiǎn)單介紹和使用2017-03-03Android編程實(shí)現(xiàn)類似于圓形ProgressBar的進(jìn)度條效果
這篇文章主要介紹了Android編程實(shí)現(xiàn)類似于圓形ProgressBar的進(jìn)度條效果,結(jié)合實(shí)例形式分析了Android通過自定義View實(shí)現(xiàn)圓形進(jìn)度條效果的操作方法,需要的朋友可以參考下2017-03-03android創(chuàng)建手勢(shì)識(shí)別示例代碼
使用一些瀏覽器或者輸入法應(yīng)用時(shí)會(huì)有一些手勢(shì)操作,還可以自定義手勢(shì)。這些神奇的操作是怎么做的呢?這一篇重點(diǎn)記錄手勢(shì)的識(shí)別和創(chuàng)建2014-01-01Android開發(fā)基于ViewPager+GridView實(shí)現(xiàn)仿大眾點(diǎn)評(píng)橫向滑動(dòng)功能
這篇文章主要介紹了Android開發(fā)基于ViewPager+GridView實(shí)現(xiàn)仿大眾點(diǎn)評(píng)橫向滑動(dòng)功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-09-09