内存泄漏原因
当应用不需要在使用某个对象时候,忘记释放为其分配的内存,导致该对象仍然保持被引用状态(当对象拥有强引用,GC无法回收),从而导致内存泄漏。
常见的内存泄漏源头
泄漏的源头有很多,有开源的第三方框架引起的;也有android系统自身造成的,比如webview的内存泄漏;还有一个是我们可以控制的,就是自身编码失误或者逻辑不严谨引起的内存泄漏。
常见的内存泄漏以及解决方案
- Context 引起的内存泄漏
常见问题:
这个是最常见的,因为Activity经常要用到上下文Context,很有可能Activity作为Context传递给某些类,Activity生命周期结束之后,某些类仍然存活并保持着该Activity的引用,保持引用就无法被回收。从而导致内存泄漏。
解决方案:
- 下次如果要传入context给某些类的时候,最好是用ApplicationContext,这样可以有效避免内存泄漏
- 在界面销毁的时候,手动释放掉引用过activity的context
- Static 静态变量
常见问题:
我们有时候会为了方便,设置某个Activity或者View为静态变量,但是你要知道,static变量是要贯穿整个应该的生命周期,就是意味着即使Activity销毁,static变量也不会销毁,所以,如果你把View或者Activity设置为静态变量,这会导致当前的Activity会一直存在,从而导致内存泄漏
解决方案:
- 尽量避免使用static变量
- 如果非要使用的话,记得在界面销毁的时候,把静态变量也释放掉,简单说就是把静态变量置空,如staticView=null
- 非静态内部类、匿名内部类持有外部类的引用
常见问题:
我们在使用AsyncTash、Handler、TimerTask、Thread的时候,为了方便,直接new一个匿名内部类对象,殊不知我们在new一个的时候,编译器在编译的时候会自动为内部类的构造方法加上外包类的引用,所以这些匿名内部类会持有Activity,当这些匿名内部类处理非常耗时的操作时候,就算Activity生命周期结束,也不会被销毁,这就会造成内存泄漏。
解决方案:
- 当Activity销毁的时候,对不需要的匿名内部类进行任务停止操作
- 使用静态内部类,静态内部类内部使用弱引用来引外外部类,这样当Activity销毁的时候,弱引用是可以被回收的
- 其他引起的泄漏
- 我们在使用系统服务的时候,比如注册了一些广播监听,在使用完后,要释放掉.
- 我们在给View绘制动画的时候,View被动画持有,而Activity又被View持有引用,导致Activity也无法释放。所以在Activity销毁时,调用animator.cancel()来停止动画
为了方便排查内存泄漏谷歌以及第三方厂家为我们提供了对应的内存分析工具,下面列出常用的三种内存泄漏分析工具。
常用分析工具
- MAT :eclipse时代的分析工具
- Android Monitor:Android Studio 自带的分析工具
- LeakCanary: Square开源的内存泄漏探测器