Android Handle詳解

一响迂、什么是Handler

Handler 、 Looper 殃饿、Message 這三者都與Android異步消息處理線程相關(guān)的概念饮寞。那么什么叫異步消息處理線程呢?

異步消息處理線程啟動后會進入一個無限的循環(huán)體之中列吼,每循環(huán)一次幽崩,從其內(nèi)部的消息隊列中取出一個消息,然后回調(diào)相應(yīng)的消息處理函數(shù)寞钥,執(zhí)行完成一個消息后則繼續(xù)循環(huán)慌申。若消息隊列為空,線程則會阻塞等待理郑。

說了這一堆蹄溉,那么和Handler 、 Looper 您炉、Message有啥關(guān)系柒爵?其實Looper負(fù)責(zé)的就是創(chuàng)建一個MessageQueue,然后進入一個無限循環(huán)體不斷從該MessageQueue中讀取消息赚爵,而消息的創(chuàng)建者就是一個或多個Handler 棉胀。

二法瑟、handler的使用方法

1、handle.sendMessge


2唁奢、handler.post(runable)方法

handler.post()方法最終調(diào)用的還是sendMessage方法霎挟。


默認(rèn)創(chuàng)建了一個message對象。

可以看到麻掸,在getPostMessage中酥夭,得到了一個Message對象,然后將我們創(chuàng)建的Runable對象作為callback屬性脊奋,賦值給了此message.

注:產(chǎn)生一個Message對象熬北,可以new ?,也可以使用Message.obtain()方法狂魔;兩者都可以蒜埋,但是更建議使用obtain方法,因為Message內(nèi)部維護了一個Message池用于Message的復(fù)用最楷,避免使用new 重新分配內(nèi)存整份。

在dispatchMessage方法中,如果message.callback,這個callback就是上面的ranable對象籽孙,然后就是調(diào)用handleCallback()方法,執(zhí)行run方法烈评。



三、handler 機制的原理


Handle的構(gòu)造方法犯建,主要是或者一個Looper對象讲冠,線程的消息循環(huán)。

通過Looper.myLooper()獲取了當(dāng)前線程保存的Looper實例适瓦,然后在又獲取了這個Looper實例中保存的MessageQueue(消息隊列)竿开,這樣就保證了handler的實例與我們Looper實例中MessageQueue關(guān)聯(lián)上了。

隨后玻熙,我們會經(jīng)常調(diào)用sendMessage方法否彩,

public final boolean sendMessage(Message msg)

{

returnsendMessageDelayed(msg,0);

}

接著是sendMessageDelayed方法。

我們有來到了sendMessageAtTime方法嗦随,然后有調(diào)用enqueueMessage()方法列荔。


最后來了MessageQueue這個隊列中,執(zhí)行了quene.enqueueMessage()方法枚尼。也就是說handler發(fā)出的消息贴浙,最終會保存到消息隊列中去。

最后Looper的loop的方法中署恍,調(diào)用了handler.dispatchMessage崎溃,完成了消息發(fā)送。


ThreadLocal

實現(xiàn)一個線程本地的存儲锭汛,也就是說笨奠,每個線程都有自己的局部變量袭蝗。所有線程都共享一個ThreadLocal對象,但是每個線程在訪問這些變量的時候能得到不同的值般婆,每個線程可以更改這些變量并且不會影響其他的線程到腥,并且支持null值。

Looper

Looper用于封裝了android線程中的消息循環(huán)蔚袍,默認(rèn)情況下一個線程是不存在消息循環(huán)(message loop)的乡范,需要調(diào)用Looper.prepare()來給線程創(chuàng)建一個消息循環(huán),調(diào)用Looper.loop()來使消息循環(huán)起作用啤咽,從消息隊列里取消息晋辆,處理消息。

對于Looper主要是prepare()和loop()兩個方法宇整。

首先看prepare()方法

Looper.prepare()方法瓶佳,是為當(dāng)年線程設(shè)置一個Looper對象,使用ThreadLocal是保證每個線程的Looper是唯一的鳞青。其中Android主線程的Looper實在ActivityThread創(chuàng)建的時候就已經(jīng)創(chuàng)建霸饲,所以,我們使用Handle的時候臂拓,并沒有執(zhí)行Looper.prepaer方法厚脉。

sThreadLocal是一個ThreadLocal對象,可以在一個線程中存儲變量胶惰∩倒ぃ可以看到,將一個Looper的實例放入了ThreadLocal孵滞,判斷了sThreadLocal是否為null中捆,否則拋出異常。這也就說明了Looper.prepare()方法不能被調(diào)用兩次坊饶,同時也保證了一個線程中只有一個Looper實例~相信有些哥們一定遇到這個錯誤轨香。


在Looper的構(gòu)造方法中創(chuàng)建一個MessageQueue實例。


在Looper的loop方法 有一個阻塞時的消息循環(huán)幼东,只有要消息傳入,就會調(diào)用Handler.dispatchMessage();

其中?MessageQueue的核心方法科雳,next()方法就是從MessageQueue隊列中獲取信息根蟹。從源碼分析中可以看出




從上面的源碼中我們知道:隊列被激活之后,首先判斷隊首是不是消息屏障糟秘,如果是則跳過所有的同步消息简逮,查找最先要處理的異步消息。如果第一個待處理的消息還沒有到要處理的時機則設(shè)置激活等待時間尿赚;否則這個消息就是需要處理的消息散庶,將該消息設(shè)置為inuse蕉堰,并將隊列設(shè)置為非 blocked狀態(tài),然后返回該消息悲龟。next()方法是一個無線循環(huán)的方法屋讶,如果消息隊列中沒有消息,那么next()方法會一直阻塞须教,當(dāng)有新消息到來時皿渗,next會將這條消息返回同時也將這條消息從鏈表中刪除。


Looper主要作用:

1轻腺、與當(dāng)前線程綁定乐疆,保證一個線程只會有一個Looper實例,同時一個Looper實例也只有一個MessageQueue贬养。

2挤土、loop()方法,不斷從MessageQueue中去取消息误算,交給消息的target屬性的dispatchMessage去處理仰美。

好了,我們的異步消息處理線程已經(jīng)有了消息隊列(MessageQueue)尉桩,也有了在無限循環(huán)體中取出消息的哥們筒占,現(xiàn)在缺的就是發(fā)送消息的對象了,于是乎:Handler登場了蜘犁。



四翰苫、handler 引起的內(nèi)存泄漏以及解決方法





參考文獻(xiàn)


Android 異步消息處理機制 讓你深入理解 Looper、Handler这橙、Message三者關(guān)系


MessageQueue工作原理

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末奏窑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子屈扎,更是在濱河造成了極大的恐慌埃唯,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,734評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鹰晨,死亡現(xiàn)場離奇詭異墨叛,居然都是意外死亡,警方通過查閱死者的電腦和手機模蜡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評論 3 394
  • 文/潘曉璐 我一進店門漠趁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人忍疾,你說我怎么就攤上這事闯传。” “怎么了卤妒?”我有些...
    開封第一講書人閱讀 164,133評論 0 354
  • 文/不壞的土叔 我叫張陵甥绿,是天一觀的道長字币。 經(jīng)常有香客問我,道長共缕,這世上最難降的妖魔是什么洗出? 我笑而不...
    開封第一講書人閱讀 58,532評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮骄呼,結(jié)果婚禮上共苛,老公的妹妹穿的比我還像新娘。我一直安慰自己蜓萄,他們只是感情好隅茎,可當(dāng)我...
    茶點故事閱讀 67,585評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嫉沽,像睡著了一般辟犀。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绸硕,一...
    開封第一講書人閱讀 51,462評論 1 302
  • 那天堂竟,我揣著相機與錄音,去河邊找鬼玻佩。 笑死出嘹,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的咬崔。 我是一名探鬼主播税稼,決...
    沈念sama閱讀 40,262評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼垮斯!你這毒婦竟也來了郎仆?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,153評論 0 276
  • 序言:老撾萬榮一對情侶失蹤兜蠕,失蹤者是張志新(化名)和其女友劉穎扰肌,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體熊杨,經(jīng)...
    沈念sama閱讀 45,587評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡曙旭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,792評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了晶府。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片夷狰。...
    茶點故事閱讀 39,919評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖郊霎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情爷绘,我是刑警寧澤书劝,帶...
    沈念sama閱讀 35,635評論 5 345
  • 正文 年R本政府宣布进倍,位于F島的核電站,受9級特大地震影響购对,放射性物質(zhì)發(fā)生泄漏猾昆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,237評論 3 329
  • 文/蒙蒙 一骡苞、第九天 我趴在偏房一處隱蔽的房頂上張望垂蜗。 院中可真熱鬧,春花似錦解幽、人聲如沸贴见。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽片部。三九已至,卻和暖如春霜定,著一層夾襖步出監(jiān)牢的瞬間档悠,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評論 1 269
  • 我被黑心中介騙來泰國打工望浩, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留辖所,地道東北人。 一個月前我還...
    沈念sama閱讀 48,048評論 3 370
  • 正文 我出身青樓磨德,卻偏偏與公主長得像缘回,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子剖张,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,864評論 2 354

推薦閱讀更多精彩內(nèi)容