持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第31天,点击查看活动详情
常见的泄漏模式
1) 静态引用Activity
Activity 是一个可以多次创建和销毁的对象。但是,如果您将 Activity 被静态持有,即使它被生命周期删除,GC 也无法收集它,因为它在应用程序在内存中时仍然存在。因此,在Activity中使用静态变量时要非常小心。如果静态变量有可能直接或间接引用 Activity,onDestroy()
则应中断引用。
案例
- 在静态变量中引用 Activity 时
- 从静态视图引用 Activity 时。
- 将 Activity 引用传递给单例对象时。
2) 由于使用 Inner & Anonymous 类而导致的 Activity 泄漏
内部类的特点是能够访问外部类的变量。在这种情况下,当内部/匿名类的维护时间长于外部类时,就会发生泄漏,因为内部类具有必须维护外部类的引用的特性。因此,为了避免泄漏的风险,内部/匿名类使用静态类。
案例
- 当在 Activity 中使用 Thread、handler 和 AsyncTask 时
3)由于线程使用导致的Activity泄漏
线程可以比Activity工作更长的时间。因此,线程的工作应该在onDestroy()
之前.
内存泄漏导致的问题
-
内存不足
如果发生内存泄漏,则不会返还之前占用的内存。在这种情况下,再次请求内存,导致更多的内存占用。但是,由于内存是有限制的,如果不能再分配到内存,app就会因为内存不足而被强制终止。如果应用程序由于内存不足而终止,用户会遇到强制终止。
-
GC发生时,停止UI渲染和事件处理。
当发生内存泄漏时,Android系统会导致频繁的GC。当 GC 发生时,UI 渲染和事件处理将停止。比如在60hz设备下大约会在16ms内绘制屏幕。如果 GC 需要很长时间,屏幕便会丢帧。用户认为应用程序很慢。此外,在严重的情况下,还会发生ANR。
注意:对于通常需要超过 100 毫秒到 200 毫秒的任务,用户会认为应用程序运行缓慢。
总结
我们必须对 GC 的工作原理有一个很好的理解。为了找到内存泄漏,我们可以借助 android studio profiler
进行分析,也可以通过集成LeakCanary
进行分析。尽管如此,也还是要小心编写代码。