從源碼角度看Handler為何會(huì)發(fā)生內(nèi)存泄露

首先我們看最常見(jiàn)的handler寫(xiě)法:

為什么handler會(huì)導(dǎo)致內(nèi)存泄露呢鞭铆?是因?yàn)閮?nèi)部類持有了外部類的引用引起的嗎墩剖?但是我們?nèi)粘?xiě)代碼中也有很多場(chǎng)景使用了內(nèi)部類薄湿,為啥那些情況沒(méi)有內(nèi)存泄露呢惊奇,今天我們就來(lái)分析根本本質(zhì)原因柒爵。

內(nèi)存泄露本質(zhì)就是已分配的內(nèi)存無(wú)法被回收

原因:長(zhǎng)生命周期的對(duì)象持有短生命周期對(duì)象的引用闸氮。

一般從引用鏈來(lái)分析內(nèi)存泄露原因:

首先我們上述寫(xiě)的就是Handler這個(gè)內(nèi)部類持有了外部了外部Activity引用鹦蠕,那么就是Handler->Activity士败,下面我們繼續(xù)看是誰(shuí)持有了Handler。

當(dāng)我們調(diào)用handler.sendMessage方法時(shí)最終會(huì)調(diào)用enqueueMessage方法

然后會(huì)把當(dāng)前handler 也就是this賦值給message的target屬性

那么到這里也就意味著message持有了Handler俘枫。所以我們Message->Handler->Activity 繼續(xù)看 直到我們找到可以作為Gcroot的腥沽。那么Message又被誰(shuí)持有呢?



在MessageQueue種有enqueueMessage添加消息往隊(duì)列中鸠蚪,這樣Message被MessageQueue所持有了今阳。MessageQueue->Message->Handler->Activity,繼續(xù)往下看


當(dāng)Looper的構(gòu)造方法中茅信,需要初始化messagequeue盾舌,此時(shí)消息隊(duì)列被Looper所持有。

Looper->MessageQueue->Message->Handler->Activity



可以看到主線程中ActivityThread的main方法中會(huì)調(diào)用Looper.prepareMainLooper方法蘸鲸,進(jìn)而構(gòu)造了一個(gè)Looper妖谴,然后把Looper放到TheadLocal,并放到主線程的ThreadLocalMap中酌摇,也就是說(shuō)這個(gè)looper是主線程持有的膝舅,是無(wú)法被釋放掉的。

ActivityThread->Looper->MessageQueue->Message->Handler->Activity窑多。

所以從這條引用鏈來(lái)看仍稀,當(dāng)Acticity被銷毀了,但是依然被ActvityThread所間接持有埂息,不會(huì)被回收技潘,造成內(nèi)存泄露。

解決方案:

1 使用靜態(tài)內(nèi)部類千康,根據(jù)java特性享幽,不會(huì)持有外部類的引用。Handler->Activity后面這條鏈就直接斷掉了吧秕。也就是Activity銷毀可以被回收了

2 弱引用加上靜態(tài)內(nèi)部類

弱引用引用的對(duì)象具有更短的生命周期琉闪,開(kāi)發(fā)者無(wú)需擔(dān)心內(nèi)存被占用沒(méi)有及時(shí)釋放導(dǎo)致內(nèi)存泄露問(wèn)題,但也會(huì)引發(fā)弱引用對(duì)象空指針問(wèn)題砸彬,需要注意判空颠毙。(kotlin有安全機(jī)制)

3 移除消息

會(huì)調(diào)用下面Message的recycleUnchecked方法

這里會(huì)將handler賦值為null,會(huì)清空MessageQueue里面所有的Message砂碉。也就是說(shuō)能把Message -> Handler的鏈條斷開(kāi)蛀蜜。達(dá)到ActivityThread不能間接持有Activity。

總結(jié):主要分析了Handler為何會(huì)導(dǎo)致內(nèi)存泄露增蹭,其實(shí)不是內(nèi)部類導(dǎo)致的滴某,而是Handler被長(zhǎng)時(shí)間生命周期對(duì)象所持有,形成了ActivityThread->Looper->MessageQueue->Message->Handler->Activity的持有鏈滋迈。才導(dǎo)致了Activity無(wú)法被回收霎奢。

解決方案:

1 使用Activity退出時(shí),清空MessageQueue的所有Message饼灿。將Handler置為Null幕侠。

2 使用static修飾內(nèi)部類,內(nèi)部類寫(xiě)出靜態(tài)的碍彭。

3 在Handler中晤硕,使用弱引用持有Activity對(duì)象,讓Activity對(duì)象生命周期更短庇忌,就能保證在垃圾回收時(shí)被正澄韫浚回收。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末皆疹,一起剝皮案震驚了整個(gè)濱河市疏橄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌略就,老刑警劉巖软族,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異残制,居然都是意外死亡立砸,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)初茶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)颗祝,“玉大人,你說(shuō)我怎么就攤上這事恼布÷荽粒” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵折汞,是天一觀的道長(zhǎng)倔幼。 經(jīng)常有香客問(wèn)我,道長(zhǎng)爽待,這世上最難降的妖魔是什么损同? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任翩腐,我火速辦了婚禮,結(jié)果婚禮上膏燃,老公的妹妹穿的比我還像新娘茂卦。我一直安慰自己,他們只是感情好组哩,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布等龙。 她就那樣靜靜地躺著,像睡著了一般伶贰。 火紅的嫁衣襯著肌膚如雪蛛砰。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,301評(píng)論 1 301
  • 那天黍衙,我揣著相機(jī)與錄音泥畅,去河邊找鬼。 笑死们豌,一個(gè)胖子當(dāng)著我的面吹牛涯捻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播望迎,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼障癌,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了辩尊?” 一聲冷哼從身側(cè)響起涛浙,我...
    開(kāi)封第一講書(shū)人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎摄欲,沒(méi)想到半個(gè)月后轿亮,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胸墙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年我注,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迟隅。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡但骨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出智袭,到底是詐尸還是另有隱情奔缠,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布吼野,位于F島的核電站校哎,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏瞳步。R本人自食惡果不足惜闷哆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一腰奋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧阳准,春花似錦氛堕、人聲如沸馏臭。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)括儒。三九已至绕沈,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間帮寻,已是汗流浹背乍狐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留固逗,地道東北人浅蚪。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像烫罩,于是被迫代替她去往敵國(guó)和親惜傲。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

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