定义
当一个对象已经不需要再使用了,本应该被回收掉,而另一个正在使用的对象持有他的引用,导致对象不能被回收。因为不能被及时回收的本该被回收的内存,就产生了内存泄露。如果内存泄露太多会导致程序没有办法申请内存,最后出现内存溢出的错误。
场景
Android开发中经常出现内存泄露的点,
- 使用单例模式
- 使用匿名内部类
- 使用异步事件处理机制
Handler
- 使用静态变量
- 资源未关闭
- 设置监听
- 使用
Asynctask
- 使用
Bitmap
优化
- 当查询完数据库之后,及时关闭
Cursor
对象。 - 记得在
Activity
的onPause
方法中调用unregisterReceiver()
方法,反注册广播。 - 避免
Context
内存泄露,比如在4.0.1之前的版本上不要将Drawer
对象置为static
。当一个Drawable
绑定到了View
上,实际上这个View
对象就会成为这个Drawable
的一个CallBack成员变量,静态的SBackground持有TextView
对象lable
的引用,而lable
只有Activity
的引用,而Activity会持有其他更多对象的引用,sBackground
生命周期要长于Activity
,当屏幕旋转时,Activity
无法销毁,这样就产生了内存泄露的问题。 - 尽量不要在
Activity
中使用非静态内部类,因为非静态内部类会隐式持有外部类实例的引用,当非静态内部类的引用的生命周期长于Activity的生命周期时,会导致Activity
无法被GC
正常回收掉。 - 谨慎使用线程
Thread
,很多人会犯这样的错误:Java
中的Thread
有一个特点就是他们都是直接被GC Root
所引用,也就是说Dalvik
虚拟机对所有被激活状态的线程都是持有强引用 ,导致GC
永远都无法回收掉这些线程对象,除非线程被手动停止并置为null
或者用户直接kill掉进程操作,所以当使用线程时,一定要考虑在Activity
退出时,及时将线程也停止并释放掉。 - 使用
Handler
时,要么放在单独的类文件中, 要么就是使用静态内部类,因为静态的内部类不会持有外部类的引用,所以不会导致外部类实例的内存泄露
参考资料:
Android性能优化篇之内存优化–内存泄漏
资料