Android 常见 Memory Leak 缘由及解决办法总结

背景

在Android开发过程当中,咱们常常碰到的状况就是在咱们不清楚为何状况下,程序忽然出现Crash了。其中有一类日志相信你们都常常碰到过,这类日志就是OOM相关的日志。这类日志除了咱们知道的Bitmap操做的时候会常常致使,还有一种隐藏的较深的缘由就是内存泄露(Memory Leak)。编辑器

内存泄露产生缘由和影响:

  • 缘由:当一个Object再也不须要的时候,本该被GC回收时,可是由于另外一个正在使用的Object持有它致使不能正常的被回收,本该被回收的对象不能回收,还存留在堆内存中,此时就产生了内存泄露。
  • 影响:Android系统可以为每一个应用程序分配的内存是有限的,当一个应用程序中产生的内存泄露过多的时候,会不免致使应用程序须要的内存超过限额而致使内存溢出使得应用程序崩溃。

内存泄露的检测方式

推荐使用 LeakCanary 工具来检测应用程序是否存在内存泄露。LeakCanary是由 Square 开源的一款轻量级的第三方内存泄漏检测工具,当检测到程序中产生内存泄漏时,它将以最直观的方式告诉咱们哪里产生了内存泄漏和致使谁泄漏了而不能被回收。工具

如何避免内存泄露

一、合理使用单例模式。

单例的静态特性使得其生命周期和应用的生命周期同样长。
如图,咱们先声明一个单例对象:

而后在Activity使用的时候,习惯性的传一个this:

集成了LeakCanary后测试,发现内存泄露了:

解决方案:
通常状况下,改为以下图的写法就能够了,由于单例的生命周期和应用的同样长,这样就防止了内存泄漏。:

总结:单例模式形成泄漏的缘由是拥有更长生命周期的对象持有短生命周期对象的强引用。测试

二、使用资源时注意资源的关闭

通常状况下,容易产生内存泄露的资源主要为:File,Cursor,Stream,Bitmap,BroadcastReceiver等,这些资源在使用时建议及时关闭,不然当这些资源没有及时回收的时候,内存泄露也就产生了。针对这些资源使用,给以下建议:this

  • BroadcastReceiver 在register以后,须要在适当的时机unregister
  • Cursor、Stream、File 这类资源类型的对象每每会使用一些Cache,因此咱们在不使用的时候,应该及时关闭,以便Cache被及时回收。若是咱们仅仅把它的引用设置为null,而不去关闭他们,每每会形成内存泄露。通常建议是先close()后置为null。
  • Bitmap在不使用的时候,调用recycle()方法。目前 Android 2.3版本之后,不须要咱们手动去这样作的,这里也就是简单的交代一下。

三、 合理使用Handler避免内存泄露

在咱们使用Handler的时候,常常看到编辑器提示咱们Handler可能会形成内存泄露,通常在这种状况下,咱们能够将Handler独立出来或者使用静态内部类,这样能够避免内存泄露。
这样作的缘由是:非静态内部类会潜在的持有它所属的外部类的引用,可是静态内部类是不会的。日志

四、 合理的使用WeakReference来引用外部类的成员变量

咱们可使用WeakReference来规避好多潜在的内存泄露的问题,可是并不代表WeakReference就是解决内存泄露的金钥匙。是否使用WeakReference主要取决于对当前对问题的理解,这须要咱们对问题的的建模思想。对象

参考文章:

  1. http://www.jianshu.com/p/e3ac42a2aea2
  2. http://puretech.iteye.com/blog/2008663
相关文章
相关标签/搜索