借鉴自https://www.jianshu.com/p/ac00e370f83d
一般内存泄漏(traditional memory leak)的原因是:由忘记释放分配的内存导致的。(Cursor忘记关闭等)
逻辑内存泄漏(logical memory leak)的原因是:当应用不再需要这个对象,当仍未释放该对象的所有引用。
如果持有对象的引用,垃圾回收器是无法回收这个对象的。但是并不是说,引用被别人持有了,就是内存泄漏了。比如activity,你在用,那就不叫内存的泄漏,内存该花还是得花。但是当用户跳转到别的activity了,销毁了之前的activity,这个时候,如果之前那个activity的资源还没有被释放这就说不过去了。最典型的原因是之前的activity的实例依然被另外的对象持有着。有些显示的引用还好说,隐式的如内部类的引用,可就真的难以查出来了。
最典型的,静态activity
private Activity activity = null; public void setActivity(Activity activity) { this.activity = activity; }这个类一旦被加载了,那么好了,从现在开始,到整个应用结束,这个activity的实例一直就被维护在这里了。怎么解决?你得注意在Activity的onDestory里释放他啊。此外,不仅仅是静态的activity,静态的占大内存的资源比如View,也有内存大面积泄漏的危险,也需要进行一个释放。
(维护成弱引用也行,如private static WeakReference<MainActivity> activityReference)
内部类(async task、handler、runnable、thread、timer task等等,只要是非静态内部类+可能延时的都会啊)
不管是匿名的还是非静态的内部类,都会持有外部类的强引用。如果你这个内部类是handler,runnable等,就危险了,因为message的target会持有handler的引用,message的callback会持有runnable的引用,而runnable、handler又会隐式持有activity的实例,所以这一串链式调用上的所有实例都不会被释放,boom。还有正常的内部类(不延时的)也会出现问题,当你把这个内部类声明成静态成员变量的时候。这个时候静态的是不会被销毁的,所以内部类不会被销毁,而内部类会隐式持有activity的实例,这个时候也内存泄漏了。
(解决方式请看:Android Handler、非静态、匿名内部类的内存泄漏,用静态内部类+弱引用或handler.removeCallbackAndMessages(null)http://blog.youkuaiyun.com/qq_36523667/article/details/78945778)
Sensor Manager
通过Context.getSystemService(int name)可以获取系统服务。这些服务工作在各自的进程中,帮助应用处理后台任务,处理硬件交互。如果需要使用这些服务,可以注册监听器,这会导致服务持有了Context的引用,如果在Activity销毁的时候没有注销这些监听器,会导致内存泄漏。