如何通过最新版Android Stuido发现和解决内存泄漏
Android Sutdio版本 3.5.1
- 打开Android Sutdio Profiler工具,如果没有使用过,可以先根据这篇文章学习:Android Studio 3.0 Profiler 性能分析利器。
- 看你要查内存泄漏的时机,我这边是退出APP,看是否有内存泄漏(主要查看Activity是否被垃圾回收),多次打开并退出APP(不杀APP,只是正常退出)。
- 多次强制垃圾回收,捕获heap dump。
1、发现内存泄漏
选择图1的arrange by package,然后找到你要查看内存泄漏的Activity。
我这边是NormalModeActivityProxy,看到Allocations下面有7个实例,说明肯定是内存泄漏了,不然不会存在这么多实例,基本是没打开一次就创建一个实例,没有被垃圾回收掉。
2、解决内存泄漏
点击图2的NormalModeActivityProxy,可以出来右边的Instance View,在随便点击Instance里面的一个实例,查看到底是哪里内存泄漏了。
出现了图3的References,看到NormalModeActivityProxy的引用深度depth是16,可以一层层往引用深度depth低的查找,根引用在哪,到底是谁引起了NormalModeActivityProxy的内存泄漏。
层层打开,最终看到是在PhoneWindow中由AttachInfo如图1所示,而这个AttachInfo是由图2的mOnWindowAttachListeners引起的,再看下mOnWindowAttachListeners,是通过add方法加进去的,remove方法移除的,引起内存泄漏,肯定是只用了add方法,而没有用remove方法。
往上一层层看,到底是哪个View使用了add方法,找到图3的CardFocusHelper,然后右键Jump to Source。
果然是CardFocusHelper,add了WindowAttachListener,却没有在app退出的时候remove,只要在activity onDestroy的时候,把这个View的WindowAttachListener remove就没有内存泄露了。
view.getViewTreeObserver().addOnWindowAttachListener(new ViewTreeObserver.OnWindowAttachListener() {
@Override
public void onWindowAttached() {
//left empty
}
@Override
public void onWindowDetached() {
view.getViewTreeObserver()
.removeOnWindowAttachListener(this);
view.getViewTreeObserver()
.removeOnScrollChangedListener(CardFocusHelper.this);
}
});