Android内存泄露概述
了解Android内存泄露之前,需要对java的内存管理和GC机制有个简单的了解。
Android内存泄露的根本原因是引用者的生命周期大于被引用者。举个例子,有对象A,B,B有A的强引用,GC要回收A时发现B还未销毁,所以A也未能被回收。
Android的内存泄露后果
- 直接后果是,内存泄露导致空间浪费,最终导致内存溢出;
- 间接后果是,内存不足导致频繁GC,系统性能下降
Android内存泄露场景
- 单例模式中引用四大组建,最常见的是单例中引用Activity的context,导致该Activity在内存中存活的周期和Application一样长,GC无法正常回收。
解决办法:单例模式应用ApplicationContext,该引用和应用的生命周期一样长 - 非静态内部类或匿名内部类,该类对象持有外部类的强引用,如果该类的对象进行耗时操作,无法短期内被回收,那他持有的外部对象也无法及时回收,典型场景有:匿名Thread类异步执行耗时操作,非静态Handler对象,其中有未完成的异步信息。
解决办法:内部类如果任务繁重,可以考虑使用静态内部类,静态内部类独立于外部类存在,典型的应用场景如RecyclerView中的VIewHolder。 - 集合中存储静态对象,导致集合占用的空间无法及时释放。
解决办法:。。。 - 资源没有关闭,例如文件操作、网络流、广播未注销、Service脱离Activity未停止运行、观察者模式未解除监听等等。
解决办法:养成良好的编程习惯,成对出现的open,close要一起使用。
补充学习一下java的各种引用
- 强引用:最通用的引用,比如 B b = new B(),b就是一个强引用,这样该引用存在,GC就不会回收,这也是导致java内存泄露的根本原因;
- 软引用:当内存不够时,GC会先回收这类引用;SoftReference bs = SoftReference(b);
- 弱引用:当GC发现一个对象只有弱引用时,马上回收它,WeakReference sr = new WeakReference(b);
- 虚引用:类似于占位符,不影响实际对象的生命周期,GC该怎么做就怎么做。
综上,是java提供的几种引用机制,如果我们加以利用,可以一定程度上减少内存泄露情景,具体用法网上很多,我也正在学习当中。