本章主要介绍使用Android Studio 检测内存泄漏 、分析内存泄漏原因及解决方法:

如果不懂何为内存泄漏的朋友请先看这篇文章:http://blog.csdn.net/hudashi/article/details/7050885
一、使用Android Studio检测内存泄漏
打开Android Studio,编译代码,在模拟器或者真机上运行App,然后点击,在Android Monitor下点击Monitor对应的Tab,进入如下界面:



在Memory一栏中,可以观察不同时间App内存的动态使用情况,点击可以手动触发GC,点击可以进入HPROF Viewer界面,查看Java的Heap,如下图:



Reference Tree代表指向该实例的引用,可以从这里面查看内存泄漏的原因,Shallow Size指的是该对象本身占用内存的大小,Retained Size代表该对象被释放后,垃圾回收 器能回收的内存总和。
下面以我自己写的项目为例,来一探内存泄漏检测的方法。
打开Android Studio,编译代码,运行APP,把所有的功能都使用一遍,然后就从Memory Monitor里面观察App的内存使用曲线,突然发现,纳尼!!!怎么内存使用越来越大了,这就很有可能是发生内存泄漏了,然后点击手动进行GC,再点击观看JavaHeap,点击Analyzer Task,Android Monitor就可以为我们自动分析泄漏的Activity啦,分析出来如下图所示



在这里,我们可以看出,有六个地方发生了内存泄漏!!!接下来就一一探索下泄漏的原因吧!
先从第一个泄漏的Activity开始吧:首先找到该活动被引用的对象(如上图:)
持有该活动的对象是:WebView ,在这里对于 WebView引起内存泄漏的原因及解决方案推荐一篇文章:http://blog.csdn.net/u012210186/article/details/52608090
我这里的解决方法是:将WebView所在的活动单独放在一个进程中: 1.AndroidMainfest.xml文件配置中将WebView所在的Activity 加上:android:process="packagename.web"
<activity
android:name=".ui.webview.MyWebView"
android:launchMode="singleTask"
android:process="packagename.web"
android:screenOrientation="portrait"/>
2.在该活退出时结束该进程:
结束方法有很多,我是直接在onDestroy() 函数中System.exit(0); 直接退出虚拟机,一了百了,省了很多代码
@Override
protected void onDestroy() {
super.onDestroy();
System.exit(0);
}
注:此时在进入跳转到WebView所在的活动切换时会出现黑屏,这个解决方法就看我上一篇转载的文章:《activity跳转黑屏处理》

好了,到此时,第一个内存泄漏已经解决,那么来看第二个内存泄漏: 按照同样的方法去找原因:结果发现,持有当前活动的对象是一个Fragment的单例,而这个fragment里又出现了WebView....,好吧,犯二了,解决方案同上!
第三个内存泄漏:
泄漏原因:该活动布局使用的是viewpager + fragment,里面有多个fragment可以滑动切换,fragment使用的是单例。由于单例的生命周期是与进程一致的,所以会导致当前活动销毁时,fragment实例还在。
解决方案:在Fragment中的onDestroy()函数中把fragment实例置空:
@Override
public void onDestroy() {
if (fragment != null ){
handler.removeCallbacksAndMessages(null);
handler = null;
fragment.onDestroyView();
fragment = null;
}
System.gc();
super.onDestroy();
}

第四个内存泄漏:原因与第三个相同.....再一次犯二了.....
第五个内存泄漏:
同样到找持有该活动的实例,定位实例中的代码,发现:此处使用了数据库未关闭:
sqLiiteDatabase = SQLiteUitl.getSQLiiteDatabase(context);
private void addSQLite(ArrayList<DataDomain.Mods> data) {
sqLiiteDatabase.add(data);
}

解决方法:在活动退出中关闭数据库:
@Override
protected void onDestroy() {
sqLiiteDatabase.close();
handler.removeCallbacksAndMessages(null);
handler = null;
System.gc();
super.onDestroy();
}

最后一个内存泄漏的地方:
持有该活动的对象是一个非静态的内部类: 当前活动声明了一个静态变量:
public static UpdateActivity activity;
UpdateActivity即为当前的Activity,方便成员变量又被内部类引用,所以造成了内存泄漏。 解决方法:把静态改为非静态即可:
public UpdateActivity activity;

好了,到此为止,这六处引起内存泄漏的地方已经解决完毕,再运行起来APP,那是杠杠地...
其实引起内存泄漏的原因有很多,常见的:
1.BraodcastReceiver,ContentObserver,FileObserver,Cursor在Activity onDeatory或者某类声明周期结束之后一定要unregister或者close掉,否则这个Activity类会被system强引用,不会被内存回收。
2.不要直接对Activity进行直接引用作为成员变量,如果不得不这么做,请用private WeakReference mActivity来做,相同的,对于Service等其他有自己生命周期的对象来说,直接引用都需要谨慎考虑是否会存在内存泄露的可能。
3.对 Context 保持了一个长生命周期的引用。
4.活动退出时handler未清空消息列队,(可以看下,我上面的代码中,在onDestroy()函数中,只要是该活动有用到handler,我都写有:handler.removeCallbacksAndMessages(null); handler = null;)

更多相关文章

  1. APNS开源包的内存泄露问题
  2. 记一次java内存分析
  3. Java对象创建的过程及对象的内存布局与访问定位
  4. Java并发编程(四)Java内存模型
  5. java内存垃圾回收模型
  6. OpenGL es 2.0使用shadow mapping方法制作阴影时,阴影穿透实体现
  7. 内存探究记录
  8. MAT:如何诊断“字节”的x实例,由“”占用y (z%)字节的“内存问题
  9. Android查看应用的最大可用内存及其使用情况

随机推荐

  1. DisplayMetrics简介
  2. android View 概述
  3. android的selector背景选择器
  4. Android 关机解析
  5. Android规范详解
  6. Android textview 只显示一行,多余部分显
  7. Android 文件格式
  8. Android(安卓)之 下拉框(Spinner)的使用
  9. 使用 Fiddler 对android模器进行Http监控
  10. Android Studio3.0新特性及安装图文教程