本章主要介绍使用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"
    android:name=".ui.webview.MyWebView"    android:launchMode="singleTask"    android:process="packagename.web"    android:screenOrientation="portrait"/>
2.在该活退出时结束该进程: 结束方法有很多,我是直接在onDestroy() 函数中System.exit(0); 直接退出虚拟机,一了百了,省了很多代码
@Overrideprotected void onDestroy() {    super.onDestroy();    System.exit(0);}
注:此时在进入跳转到WebView所在的活动切换时会出现黑屏,这个解决方法就看我上一篇转载的文章:《 activity跳转黑屏处理》
好了,到此时,第一个内存泄漏已经解决,那么来看第二个内存泄漏: 按照同样的方法去找原因:结果发现,持有当前活动的对象是一个Fragment的单例,而这个fragment里又出现了WebView.... ,好吧,犯二了,解决方案同上!
第三个内存泄漏:
泄漏原因:该活动布局使用的是viewpager + fragment,里面有多个fragment可以滑动切换,fragment使用的是单例。由于单例的生命周期是与进程一致的,所以会导致当前活动销毁时,fragment实例还在。
解决方案:在Fragment中的onDestroy()函数中把fragment实例置空:
@Overridepublic 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 data) {    sqLiiteDatabase.add(data);}

解决方法:在活动退出中关闭数据库:
@Overrideprotected 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. Android内存优化总结
  2. Android(安卓)Dalvikvm 内存管理理解
  3. Android(安卓)操作系统的内存回收机制(转载)
  4. Android解决加载大图片时内存溢出的问题
  5. davlik虚拟机内存管理之一——内存分配
  6. 【Xcode应用】iOS性能分析
  7. Android开发之旅:活动与任务[转]
  8. 【转】Android内存泄漏简介
  9. Android学习笔记2:Hello World程序解析

随机推荐

  1. Android(安卓)禁止屏幕旋转 & 旋转屏幕时
  2. Android(安卓)依赖库的使用
  3. 【Medium 万赞好文】ViewModel 和 LIveDa
  4. Activity class {package/class} does no
  5. Activity中的onSaveInstanceState()解析
  6. android SeekBar 样式大全
  7. Android调用WebService系列之请求调用
  8. Android(安卓)两Activity之间动画效果(1)--
  9. Android之开关飞行模式
  10. android显示图片的两种方法