说起性能优化,大多数脑海里便会出现启动优化、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工具方法有很多,大家可以多搜索一下。先到这里吧。