概述

Android内存泄漏,也就是我们常说的OOM(out of memory)OOM的后果大家都知道,严重影响APP的体验,轻则卡顿,重则闪退。而且内存泄漏在低端机上一般都会伴随着ANR,所以一定要重视它。

造成内存泄漏的常见因素有:

  • IO操作
  • Bitmap
  • Context
    • 单例持有引用
  • Service
    • BroadcastReceiver
    • ContentObserver
  • Handler
  • Thread

分析方法

分析内存泄漏的常用方法:

  • StrictMode, 在ApplicationonCreate中添加StrictMode代码块
  • Leakcanary,引用Leakcanary库(常规手段,仅供参与,不应完全依赖这个库)
  • monkey,模拟用户点击操作,检查是否出现泄漏(推荐,最有效的方法)
  • adb命令手动触发adb shell dumpsys meminfo packagename -d
  • Android Studio Memory Profiler,Android Studio自带的分析工具,已经非常好用了
  • MAT,终极神器,内存分析绕不开的话题(Android Studio搞不定就靠它了)

解决方案

  1. Context 如果大家收集过内存泄漏的崩溃日志,会发现大量错误都是由ContextHandler造成。 因为我们开发中会大量用到Context引用,而ContextApplicationActivityService之类的地方会有自己的实例,而ActivityService会因为生命周期的原因导致Context实例被回收,如果你继续使用其引用就会因为弱引用问题导致错误出现。 Context的引用也常见于单例模式。 所以建议大家尽可能使用ApplicationContext

  2. Bitmap Bitmap的问题一般是因为没有对使用的图片及时释放所致。 图片一般因为体积问题,会导致占用比较多的内存 解决方案:就是在ActivityonDestroy()中及时回收内存。

  3. IO操作 FileOutputStream()未关闭,IO流忘记关闭 解决方案:及时关闭IO流,避免泄露

  4. Handler泄漏 由于Activity已经关闭,Handler任务还未执行完成,其引用了Activity的实例导致内存泄露 解决方案:在Activity的onDestroy()方法回收Handler

  5. 异步线程泄露 一般发生在线程执行耗时操作时,如下载,此时Activity关闭后,由于其被异步线程引用,导致无法被正常回收,从而内存泄露 解决方案:把线程作为对象提取出来,在Activity的onDestroy()方法阻塞线程

  6. 静态成员变量 开发中会定义许多static变量,如果有大量的静态变量定义,并有引用资源,一定要在onDestroy或其他地方及时释放(把变量置空即可)