解決Android記憶體洩漏;輕鬆降低100M

安卓開發高階技術分享發表於2019-01-16

背景

今天發現有個App存在嚴重的記憶體洩漏問題,通過安裝LeakCanary找到大致方向,通過嚴格管理Timer、Presenter和Handler,輕鬆把它消耗的內容降低了100M。

過程

LeakCanary

LeakCanary是square公司提供的一個很好用的記憶體洩漏查詢工具,與MAT不同的是,它會在你執行App時檢查你的記憶體回收,並找到記憶體洩漏點,直接提示給你,比用MAT去分析日誌的形式更加簡單直接,不過缺點是LeakCanary的資訊不像MAT那麼多,很難查到更細微的問題。

LeakCanary的安裝過程很簡單,首先配置Gradle

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

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

執行App,LeakCanary會在App執行過程中不定期收集資訊,如果發現有記憶體洩漏的問題,就會在通知欄中給出提示,如XXXActivity大概因為XXX洩露了XXM記憶體,比如我們執行LeakCanary在Github上的demo,得到的提示就會像下圖這樣

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

Timer

在檢查中,在Presenter裡忘記關閉一個Timer的task,在Activity的onDestroy事件中呼叫Presenter的onDestroy

在Presenter的onDestroy中執行銷燬操作

我們看到,在Presenter銷燬元素時,做了三件事:

1.關閉執行緒(要先執行interrupt,否則休眠執行緒無法立即停止)

2.銷燬Presenter中關聯的View物件(否則會導致對應的Activity無法釋放)

3.退出Timer定時任務

Presenter

再看一遍Presenter執行銷燬操作的程式碼

 

在上圖中,我們看到Presenter在銷燬時,一定要把View銷燬掉,否則會導致對應的Activity或Fragment無法釋放,在檢查中發現有些Presenter沒有寫銷燬,考慮在以後統一實現一個Presenter的基類,在基類中實現銷燬View的程式碼

Handler

在檢查中,發現有些對話方塊彈出後無法回收記憶體,在檢查中發現了這樣的程式碼

LeakHandler

這是我們一般接觸到的典型的Handler寫法,但是注意看提示,提示中說明了這裡有洩漏風險,從避免記憶體洩漏的角度,應該改成這樣的程式碼

 

在這段寫法中,我們用static內部類去過載了一個Handler,static內部類實際上會生成一個弱引用物件,這就不會產生記憶體洩漏。

不過這樣一來,在static內部類中,我們就無法呼叫Activity的函式了,這就需要在這個Handler初始化時把Activity傳進來,直接傳進來的Activity還是可能造成記憶體洩漏,我們還要把它放到一個弱引用物件裡,通過get()函式取得Activity物件並呼叫其函式。

總結

在這次的記憶體洩漏查詢過程中,主要解決了三個問題

1.及時銷燬所有的Timer定時任務

2.及時銷燬Presenter中的View物件

3.檢查所有的Handler,改為static+弱引用的實現方式

解決這些問題後,再次執行LeakCanary,已經不再輸出記憶體洩漏的內容了,App消耗的記憶體也減少了100多M。

其實這裡解決的記憶體洩漏問題都是很淺顯的部分,能在這些地方出錯,說明這個App的記憶體洩漏已經相當嚴重了,在日常編碼中,還是要多留一份心才是。

附錄

Android高階技術大綱,以及系統進階視訊;

Android高階技術大綱

Android進階系統資料視訊

獲取方式;

加Android進階群;701740775。即可前往免費領取。免費備註一下csdn




 

相關文章