解決Android內(nèi)存泄漏—輕松降低100M

背景

今天發(fā)現(xiàn)有個(gè)App存在嚴(yán)重的內(nèi)存泄漏問題,通過(guò)安裝LeakCanary找到大致方向,通過(guò)嚴(yán)格管理Timer、Presenter和Handler,輕松把它消耗的內(nèi)容降低了100M。

過(guò)程

LeakCanary

LeakCanary是square公司提供的一個(gè)很好用的內(nèi)存泄漏查找工具,與MAT不同的是,它會(huì)在你運(yùn)行App時(shí)檢查你的內(nèi)存回收,并找到內(nèi)存泄漏點(diǎn),直接提示給你,比用MAT去分析日志的形式更加簡(jiǎn)單直接,不過(guò)缺點(diǎn)是LeakCanary的信息不像MAT那么多,很難查到更細(xì)微的問題。

LeakCanary的安裝過(guò)程很簡(jiǎn)單,首先配置Gradle

為L(zhǎng)eakCanary添加Gradle引用

然后在自定義的Application中初始化

在自定義的MyApplication中初始化LeakCanary

記得在Manifest中使用自定義的Application

在AndroidManifest中使用自定義的MyApplication

運(yùn)行App,LeakCanary會(huì)在App運(yùn)行過(guò)程中不定期收集信息,如果發(fā)現(xiàn)有內(nèi)存泄漏的問題,就會(huì)在通知欄中給出提示,如XXXActivity大概因?yàn)閄XX泄露了XXM內(nèi)存,比如我們運(yùn)行LeakCanary在Github上的demo,得到的提示就會(huì)像下圖這樣

LeakCanary典型界面

可見,直接指出了問題類和問題原因,比起MAT還是簡(jiǎn)單多了的

Timer

在檢查中,在Presenter里忘記關(guān)閉一個(gè)Timer的task,在Activity的onDestroy事件中調(diào)用Presenter的onDestroy

在Activity關(guān)閉時(shí)調(diào)用Presenter的銷毀函數(shù)

在Presenter的onDestroy中執(zhí)行銷毀操作

在Presenter中的銷毀操作

我們看到,在Presenter銷毀元素時(shí),做了三件事:

1.關(guān)閉線程(要先執(zhí)行interrupt,否則休眠線程無(wú)法立即停止)

2.銷毀Presenter中關(guān)聯(lián)的View對(duì)象(否則會(huì)導(dǎo)致對(duì)應(yīng)的Activity無(wú)法釋放)

3.退出Timer定時(shí)任務(wù)

Presenter

再看一遍Presenter執(zhí)行銷毀操作的代碼

Presenter銷毀View

在上圖中,我們看到Presenter在銷毀時(shí),一定要把View銷毀掉,否則會(huì)導(dǎo)致對(duì)應(yīng)的Activity或Fragment無(wú)法釋放,在檢查中發(fā)現(xiàn)有些Presenter沒有寫銷毀,考慮在以后統(tǒng)一實(shí)現(xiàn)一個(gè)Presenter的基類,在基類中實(shí)現(xiàn)銷毀View的代碼

Handler

在檢查中,發(fā)現(xiàn)有些對(duì)話框彈出后無(wú)法回收內(nèi)存,在檢查中發(fā)現(xiàn)了這樣的代碼

LeakHandler

這是我們一般接觸到的典型的Handler寫法,但是注意看提示,提示中說(shuō)明了這里有泄漏風(fēng)險(xiǎn),從避免內(nèi)存泄漏的角度,應(yīng)該改成這樣的代碼

AntiLeakHandler

在這段寫法中,我們用static內(nèi)部類去重載了一個(gè)Handler,static內(nèi)部類實(shí)際上會(huì)生成一個(gè)弱引用對(duì)象,這就不會(huì)產(chǎn)生內(nèi)存泄漏。

不過(guò)這樣一來(lái),在static內(nèi)部類中,我們就無(wú)法調(diào)用Activity的函數(shù)了,這就需要在這個(gè)Handler初始化時(shí)把Activity傳進(jìn)來(lái),直接傳進(jìn)來(lái)的Activity還是可能造成內(nèi)存泄漏,我們還要把它放到一個(gè)弱引用對(duì)象里,通過(guò)get()函數(shù)取得Activity對(duì)象并調(diào)用其函數(shù)。

總結(jié)

在這次的內(nèi)存泄漏查找過(guò)程中,主要解決了三個(gè)問題

1.及時(shí)銷毀所有的Timer定時(shí)任務(wù)

2.及時(shí)銷毀Presenter中的View對(duì)象

3.檢查所有的Handler,改為static+弱引用的實(shí)現(xiàn)方式

解決這些問題后,再次運(yùn)行LeakCanary,已經(jīng)不再輸出內(nèi)存泄漏的內(nèi)容了,App消耗的內(nèi)存也減少了100多M。

其實(shí)這里解決的內(nèi)存泄漏問題都是很淺顯的部分,能在這些地方出錯(cuò),說(shuō)明這個(gè)App的內(nèi)存泄漏已經(jīng)相當(dāng)嚴(yán)重了,在日常編碼中,還是要多留一份心才是。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容