1、静态变量导致内存泄漏
Activity的Context或this被赋值给一个类的静态变量,因为静态变量时类变量,除非该类在虚拟机中被卸载,否则,Activity永远被强引用,不会被GC掉。
2、属性动画导致的内存泄漏
如果动画无限循环,且没有在onDestroy中退出动画,并且,此Activity的View被动画持有,View又持有Activity,最终Activity无法释放。解决方法是在,onDestroy中调用animotor.cancel()退出动画。
3、内部类导致的内存泄漏(Handler)
private Handler mHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
...
}
};
经常会使用以上匿名类的方式来引用Handler,匿名类是内部类,
只要在对象的上下文(而不是类的上下文)建立内部类就会隐式持有外部引用(在对象实例变量后直接赋值引用、在实例方法中建立匿名类等)。
为啥会导致内存泄漏呢?
当onDestroy方法执行时,如果Handler对象没有被回收,因为它持有Activity的引用,所以Activity就不能被回收。
那为什么Handler对象没有被回收呢?
要知道MessageQueue里面的Message有一个字段是target,它会持有发送它的Handler对象的引用。设想这样一种情况,当大量使用sendMessage发送信息时,MessageQueue就会有大量Message对象,如果此时关闭Activity,那么这些Message对象就会得不到处理,他们持有Handler对象引用,Handler对象又持有Activity对象,此时就发生内存泄露了。
解决方法就是,别让Handler对象持有Activity引用:
在关闭Activity时(finish/onStop等函数中),取消还在排队的Message:
mHandler.removeCallbacksAndMessages(null);
新建一个静态内部类,但是,因为要在Handler的handleMessage中更新UI,静态内部类访问不到外部类的成员,所以就要传入弱引用包装的Activity引用,来更新UI
相关阅读:Android中的内部类引起的内存泄露
4、优先处理的常见的内存泄漏
- 非静态内部类导致的内存泄漏,如Handler;
- IO操作后没有关闭文件导致的内存泄漏,如Cursor、FileInputStream、FileOutputStream用完没关;
- 自定义View中使用TypedArray后,没有recycle;
某些地方使用了四大组件的context,在离开这些组件后仍然持有其context导致的内存泄露,使用Application的Context就可以解决这类问题,各类组件的Context的应用场景:
1、数字1:启动Activity在这些类中是可以的,但是需要创建一个新的task,一般情况不推荐;
2、数字2:在这些类中去layout inflate是合法的,但是会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用;
3、数字3:在Receiver为null时允许,在4.2或以上的版本中,用于获取黏性广播的当前值。(可以无视);
4、ContentProvider、BroadcastReceiver之所以在上述表格中,是因为在其内部方法中都有一个context用于使用。
- 还有一种不属于内存泄露,但在分析内存泄露的问题时应该一并解决:同一个APP,将图片放在不同的drawable文件夹下,在相同的设备上占用的内存情况不一样。相关阅读:关于Android中图片大小、内存占用与drawable文件夹关系的研究与分析
- UI只提供一套高分辨率的图,图片建议放在drawable-xxhdpi文件夹下(放在xxxhdpi或者更高分辨率的文件夹下没有必要,权衡利弊,照顾主流设备即可),这样在低分辨率设备中图片的大小只是压缩,不会存在内存增大的情况;
- 涉及到桌面插件或者不需要缩放的图片,放在drawable-nodpi文件夹下,这个文件夹下的图片在任何设备上都是不会缩放的。
5、内存泄漏的八种可能
- 静态Activity:静态变量引用实例本身
- 静态View:view也会持有Activity引用,所以。。
- 内部类
- 匿名类:匿名AsyncTask
- Handler:上面有
- 无限循环的Thread,因为在对象上下文定义,所以也会持有Activity引用
- 匿名TimerTask
- 使用传感器时,注册了监听器,但是没有注销
相关阅读:
Android内存泄漏的八种可能
Eight Ways Your Android App Can Leak Memory
好吧还是胡凯先生总结得好:Android性能优化系列