原因
頁面退出時,post到handler的runnable是延遲任務(wù),還未到時延酥郭,且作為非靜態(tài)內(nèi)部匿名類华坦,持有了外部TvTaobaoImp的強引用,而TvTaobaoImp持有著Activity的context不从,導致Activity沒有被回收惜姐。
分析
可以用LeakCannry檢測是否存在內(nèi)存泄漏,如果存在椿息,會出警告歹袁,并給出提示信息。作者君這里直接分析了dump下來的堆轉(zhuǎn)儲文件寝优。
TvTaoBaoImp對象持有callBack条舔,這是個runnable,非靜態(tài)內(nèi)部類乏矾,支持TvTaoBaoImp孟抗,它被post到MessageQuene隊列中,Looper會循環(huán)去取里頭的Message處理钻心,頁面退出時凄硼,該Message尚未被處理。于是一級級被持有扔役,最終導致Activity也無法被釋放帆喇。
找到泄露的地方,解決方案就非常簡單了:
1.handler作為內(nèi)部靜態(tài)類亿胸,以軟引用的方式持有外部對象坯钦。
2.由于邏輯上本身在頁面退出后不需要再執(zhí)行延時里的業(yè)務(wù)代碼,因此在頁面退出后侈玄,清空handler的message和runnable婉刀。
小結(jié)
使用延遲消息需要謹慎,注意頁面退出是否該消息還需要執(zhí)行序仙,若需要可以使用軟引用突颊,若不需要則將消息從隊列中移除。
有時候泄漏的本質(zhì)潘悼,就是彼此生命周期不一樣了律秃,一方結(jié)束,另一方還未結(jié)束治唤,不能一上來都用弱引用棒动,引用類型各有其存在的合理性,各有優(yōu)缺點宾添。作者君的業(yè)務(wù)場景船惨,實則是二者的生命周期不一致柜裸,頁面消失時,runnable也不應(yīng)該再執(zhí)行粱锐。