說起性能優化,大多數腦海裏便會出現啓動優化、UI繪製優化、內存優化等等。之前我也一直在做這些優化,一直沒有勇氣看內存泄漏的問題,覺得太難,但是,再難也要看啊,跑不了,那麼就來吧(做完發現其實也不難)。
內存泄漏的分析很簡單,Android Studio中就自帶了工具profile:
直接點擊這個按鈕就會運行應用並進入相應界面:
點擊圖片中的MEMORY就進入內存的頁面:
然後點擊左上角的下載按鈕(Record旁邊),進入詳細頁面,
可以選爲查看包內容,查看下當前運行的活動,然後右擊選中內容,選擇export,自定導出位置。
導出後需要使用SDK中的hprof-conv工具,這裏windows的用戶可以直接進入安卓的sdk文件夾下運行cmd即可,Mac用戶可以配置一個全局變量,由於我的系統版本是10.15,這裏我就寫zsh的配置方法了。
1.打開終端
2.打開 ~/.zshrc文件(如果無,則自動新建)
命令:
// 打開 ~/.zshrc文件(如果無,則自動新建)
open ~/.zshrc
3.設置環境變量
export PATH=${PATH}:/Users/zhujiang/Library/Android/sdk/platform-tools
4.保存並退出編輯
5.刷新環境變量生效
source ~/.zshrc
到這裏就都可以使用hprof-conv工具了,需要輸入以下命令將你導出的hprof文件轉換成mat-hprof文件,命令如下:
hprof-conv -z 導出的文件.hprof 轉換文件-mat.hprof
完成之後會出現的轉換的文件,接下來需要下載能分析MAT的工具,一般使用Memory Analyzer,下面是下載地址:
https://www.eclipse.org/mat/downloads.php
下載完畢後雙擊文件如果報錯的話,這是eclipse的一個bug。
解決辦法: 右鍵mat顯示包內容,進入Contents->MacOS下面,會有一個MemoryAnalyzer的命令。
打開終端,進入此路徑找到MemoryAnalyzer,運行以下命令:
./MemoryAnalyzer -data dump文件所在文件夾路徑
這樣即可啓動成功:
打開之後選擇如下選項打開剛纔轉換完成的文件:
打開之後選擇我下面的選項,然後點擊finish,如果出錯別管它,繼續進行:
進入之後選擇Overview,然後點擊Histogram。
之後就可以進入類的頁面,可以在裏面進行篩選:
下面是篩選的方法:
找見需要優化的類,按照下面的方法打開:
打開之後是如下的頁面:
發現有一個mContext持有活動的引用,導致活動無法銷燬。找到原因之後進行解決,咱們需要短了它的引用鏈,使GC可以清理調它。代碼不多,在活動的onDestory()中進行銷燬就行。
public static void fixInputMethodManagerLeak(Context destContext) {
if (destContext == null) {
return;
}
InputMethodManager imm = (InputMethodManager) destContext.getSystemService(Context.INPUT_METHOD_SERVICE);
if (imm == null) {
return;
}
String [] arr = new String[]{"mCurRootView", "mServedView", "mNextServedView"};
Field f;
Object obj_get;
for (String param : arr) {
try {
f = imm.getClass().getDeclaredField(param);
if (!f.isAccessible()) {
f.setAccessible(true);
}
obj_get = f.get(imm);
if (obj_get instanceof View) {
View v_get = (View) obj_get;
if (v_get.getContext() == destContext) { // 被InputMethodManager持有引用的context是想要目標銷燬的
f.set(imm, null); // 置空,破壞掉path to gc節點
} else {
// 不是想要目標銷燬的,即爲又進了另一層界面了,不要處理,避免影響原邏輯,也就不用繼續for循環了
break;
}
}
} catch (Throwable t) {
t.printStackTrace();
}
}
}
好了,這就是一個簡單的內存泄漏問題。如果你的頁面中有其他頁面沒有銷燬,那就證明你的頁面存在內存泄漏,就需要來這樣進行查看。使用Mat工具方法有很多,大家可以多搜索一下。先到這裏吧。