Handler內(nèi)存泄漏解決及原因分析(源碼向)

1.使用靜態(tài)內(nèi)部類和弱引用

自定義靜態(tài)內(nèi)部類繼承Handler

因為靜態(tài)內(nèi)部類不能訪問外部類的非靜態(tài)方法,所以需要有外部類的弱引用

private HandlermUIHandler =new MyUIHandler(this);

public static class MyUIHandlerextends Handler {

public final static int REFRESH_UI =0;

? ? private WeakReferencemActivity;

? ? public MyUIHandler(SleepAndReadCode activity) {

mActivity =new WeakReference<>(activity);

? ? }

@Override

? ? public void handleMessage(Message msg) {

SleepAndReadCode theActivity =mActivity.get();

? ? ? ? if (theActivity ==null){

super.handleMessage(msg);

return;

? ? ? ? }

switch (msg.what) {

case REFRESH_UI:

theActivity.refreshUI();

break;

? ? ? ? }

}

}

private void refreshUI(){

? ? //UI操作

}

2.使用Handler.removeCallbacksAndMessages()方法,不過每個handler對象都要調(diào)用一次龄寞,在activity的onDestroy()的生命周期中使用Handler.removeCallbacksAndMessages()


接下來我將從源碼分析內(nèi)存泄漏產(chǎn)生的原因腿箩,有興趣的同學(xué)可以看看疾棵。

如果你還不知道Android消息隊列模型,建議可以先去了解一下。

為什么Handler會持有activity的引用刽锤?

因為Handler在activity中創(chuàng)建,也就是new出來時朦佩,非靜態(tài)的內(nèi)部類會持有外部類的引用并思。

那為什么Handler持有activity的引用會導(dǎo)致內(nèi)存泄漏喃?

因為Message持有了handler语稠。

來看看Message是怎么持有Handler的:

p.target會在handler發(fā)送Message的時候宋彼,一般我們使用的時候用的是sendEmptyMessage或者之類的方法,最終都會通過Handler的enqueueMessage把發(fā)送方的hanlder置于Message中仙畦,于是Message便有了handler的引用

為什么Message持有了handler就會導(dǎo)致內(nèi)存泄漏喃输涕?

眾所周知UI線程在創(chuàng)建時會默認(rèn)創(chuàng)建一個Looper和Message隊列,來看看Looper中的loop()方法的源碼:



發(fā)現(xiàn)也沒什么特殊的慨畸,無非就是一個循環(huán)莱坎,循環(huán)讀取消息隊列有無Message,用完之后調(diào)用msg.recycleUnchecked()寸士,進(jìn)入看看:


發(fā)現(xiàn)這里就是把已經(jīng)使用的Message釋放掉檐什,target置為null,就沒有handler的引用了弱卡,那為什么會發(fā)生內(nèi)存泄漏喃乃正,讓我們來試想一種情況:

你的Message是延時執(zhí)行的,但是用戶可不會管婶博,點了back鍵瓮具,你的Activity應(yīng)該要被GC銷毀的,但是Message持有的Handler又有Activity的強(qiáng)引用,所以無法被GC回收名党,這時內(nèi)存泄漏就發(fā)生了垢箕;所以內(nèi)存泄漏不是一定發(fā)生的。

搞清楚為什么會發(fā)生內(nèi)存泄漏兑巾,那就知道解決辦法了条获。

1.使用靜態(tài)內(nèi)部類:適用于不用更新界面等情況,因為靜態(tài)內(nèi)部類是無法使用外部類的非靜態(tài)方法和變量的

2.使用靜態(tài)內(nèi)部類+弱引用:適用于要更新界面等情況

3.在onDestroy生命周期調(diào)用removeCallbacksAndMessages()方法

/**

* Remove any pending posts of callbacks and sent messages whose

* <var>obj</var> is <var>token</var>. ?If <var>token</var> is null,

* all callbacks and messages will be removed.

*/

public final void removeCallbacksAndMessages(Object token) {

mQueue.removeCallbacksAndMessages(this, token);

}

來看看mQueue.removeCallbacksAndMessages()方法的源碼:

之前傳入的handler不為空蒋歌,繼續(xù)執(zhí)行

p一般不為空帅掘,為空也就不會產(chǎn)生內(nèi)存泄漏了

p.target == h判斷當(dāng)前Message是否為對應(yīng)Handler的Message,這也是為什么要每個Handler對象都要調(diào)用一次

所以是當(dāng)前線程的話也為true堂油,接下來因為傳入的object為null修档,也為真,不用看p.obj==object的真假,所以可以進(jìn)入循環(huán)府框,然后清空了整個Message隊列吱窝,第二個循環(huán)不會進(jìn)入(p已經(jīng)到隊列尾,為null了)迫靖,內(nèi)存泄漏解決院峡。

那如果傳入不為空喃?

那就會進(jìn)第二個循環(huán)系宜,單獨回收對應(yīng)的Message照激。

至此,想必你對Handler內(nèi)存泄漏的原因及解決方法有了一個清楚的認(rèn)識盹牧。



手打不易俩垃,點個贊唄。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末汰寓,一起剝皮案震驚了整個濱河市口柳,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌有滑,老刑警劉巖跃闹,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異俺孙,居然都是意外死亡辣卒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門睛榄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來荣茫,“玉大人,你說我怎么就攤上這事场靴》壤颍” “怎么了港准?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咧欣。 經(jīng)常有香客問我浅缸,道長,這世上最難降的妖魔是什么魄咕? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任衩椒,我火速辦了婚禮,結(jié)果婚禮上哮兰,老公的妹妹穿的比我還像新娘毛萌。我一直安慰自己,他們只是感情好喝滞,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布阁将。 她就那樣靜靜地躺著,像睡著了一般右遭。 火紅的嫁衣襯著肌膚如雪做盅。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天窘哈,我揣著相機(jī)與錄音吹榴,去河邊找鬼。 笑死宵距,一個胖子當(dāng)著我的面吹牛腊尚,可吹牛的內(nèi)容都是我干的吨拗。 我是一名探鬼主播满哪,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼劝篷!你這毒婦竟也來了哨鸭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤娇妓,失蹤者是張志新(化名)和其女友劉穎像鸡,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體哈恰,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡只估,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了着绷。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蛔钙。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖荠医,靈堂內(nèi)的尸體忽然破棺而出吁脱,到底是詐尸還是另有隱情桑涎,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布兼贡,位于F島的核電站攻冷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏遍希。R本人自食惡果不足惜等曼,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望凿蒜。 院中可真熱鬧涉兽,春花似錦、人聲如沸篙程。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽虱饿。三九已至拥诡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間氮发,已是汗流浹背渴肉。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留爽冕,地道東北人仇祭。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像颈畸,于是被迫代替她去往敵國和親乌奇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

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