1. 內存泄漏類型html
本次內存優化,發現以下內存泄漏類型:java
Bitmap未即時釋放緩存
Handler泄漏ide
static成員泄漏優化
Callback泄漏spa
Activity leak window設計
cursor未關閉htm
內存泄漏問題詳細描述,參見《內存優化評估文檔》。對象
下面將描述不一樣內存泄漏類型的解決方案。blog
2. 內存泄漏解決方案
業務代碼沒有及時主動釋放Bitmap,容易形成短期內內存被大量佔用,進一步誘發OOM的發生。
解決方案思路有兩種狀況:
1) 對於從文件系統加載、Drawable資源加載,創建二級緩存管理該類Btimap;
2) 對於內存建立、圖形變換產生的Bitmap,由業務本身去即時釋放資源。
ImageUtis、BitmapUtils封裝了Bitmap加載/獲取的二級緩存機制,加載文件系統的Bitmap,推薦使用ImageUtils中的getBitmap系列方法。
調用ImageUtis獲取Bitmap
圖1描述了使用二級緩存管理Bitmap。
圖1使用二級緩存管理Bitmap
自行管理Bitmap
圖2描述了自行管理Bitmap釋放。
圖2自行管理Bitmap釋放
Handler泄漏的緣由,大可能是匿名構建Handler實例,從而持有外部類Activity實例致使。
解決方案思路有兩種:
1)去除Handler實例持有的外部類引用,該類思路的作法,通常是將Handler的子類定義爲靜態內部類,或者以一個單獨的類文件形式存在;
2)保證在Activity/Service退出時,清空消息隊列中與Handler有關的全部消息。
推薦使用第一種思路,實現起來簡單、高效,第二種思路雖也可實現,但要考慮的面比較多,容易產生遺漏。
圖3描述了MyCellLayout.java文件中,有一個Handler泄漏實例。
圖3 Handler泄漏實例
圖4中所示代碼對圖3中的Handler泄漏作了修復。
圖4 圖3 Handler泄漏修復
Static類成員,其生命週期與App生命週期近乎等長,在不合理的設計中,static類成員持有的對象,其內部持有Activity實例等致使。
解決方案思路有兩種:
5)在static類成員持有的對象內部, 規避持有Activity實例;
6)避免使用static成員。
圖5描述了 GlobalMsgProcessHelper.java中static類成員泄漏。
圖5 static類成員泄漏
圖6是對圖5 static類成員泄漏的修復。
圖6 圖5 static類成員泄漏修復
Callback直接或間接持有Activity實例等致使。
解決方案思路,在Callback對象內部規避持有Activity實例。
參見DeviceCategoryView.java DeviceCategoryDownloadCallback。
Activity異外先於Dialog退出,致使本異常拋出,本質也是一種內存泄漏。
構建BaseDialog,使全部自定義Dialog均擴展自此類,在BaseDialog內部實如今Activity退出前先行銷燬的邏輯。
圖7 描述了BaseDialog實現自釋放邏輯。
圖8 描述了CommonDialog派生自BaseDialog
圖7 BaseDialog實現自釋放邏輯
圖8 CommonDialog派生自BaseDialog
Cursor使用完後等致使。
解決方案思路,在Cursor使用完後釋放資源。
圖9描述了Cursor泄漏修復。
圖9 Cursor泄漏修復