Android解决内存泄漏的实战记录

前言

关于Android内存优化、内存泄漏相关的文章很多,不过大部分是给读者知识上的准备。本文将记录和分享本人在项目中的实战经验,希望能从另一个角度写出价值~~

知识储备

首先,理解一下什么是内存泄漏:当应用不再需要这个对象,但仍未释放该对象的所有引用。这样解释有点抽象。或者这样说,一般情况下,在我们Android开发中,当一个Activity对象自身执行onDestroy()后,仍被其他对象持有者,使JVM不能回收该Activity对象,就造成了内存泄漏(这里读者必须要对垃圾回收的可达性分析法有一定理解,这里不作详解,可参考Carson的一篇文章:JVM:判断一个Java对象是否存活)。

实战纪录

通过Leak Canary的监测和翻查GitLab上的Commits记录,大致把内存泄漏的成因分为以下几种情况。

情况一:属性动画忘记取消

这种错误在实战中出现得比较多。特别是那种设置了无限循环模式的动画,理论上是一直不会释放的,积累多几个界面的泄漏就很容易造成OOM。如果不是无限循环模式,理论上等动画播完后就会在适当时候被回收,危害性还不算大。
为什么动画会导致内存泄漏呢?我猜是动画(数值)的更新肯定也离不开线程间的通讯机制,而handler肯定得持有界面控件的引用才能更新动画,控件又持有Activity实例,所以就回收不到Activity了。查看动画的start()方法,里面有个AnimationHandler,嗯,八九不离十了。
解决方法:记得在onDestroy()方法中取消掉动画就行,特别是无限循环的动画!!

情况二:RxJava的定时任务没有取消

当在页面中通过Observable.interval()执行循环任务或者delay()延时任务等,退出界面忘记执行Subscription.unsubscribe()来取消任务。
泄漏的原因和危害性不用多说,可参考情况一。
解决方法:记得在onDestroy()方法中取消掉RxJava任务就行,特别是无限循环的任务!!

情况三:第三方服务的耗时操作

在使用到七牛上传文件的页面里,当上传任务还未执行完,用户就按返回键退回上一界面,而未为用户取消上传任务。
因为上传任务的回调是直接引用着该Activity对象的,所以上传未完成的话,Activity对象也回收不了。
解决方法:在onDestroy()方法中通知第三方服务取消任务就行。一般第三方服务都会考虑到这个问题,可以很方便的取消任务。

情况四:EventBus没有反注册

忘记在onDestroy()方法中执行EventBus.getDefault().unregister()方法。
显然,EventBus会持有此Activity对象,无法回收。
解决方法:在onDestroy()方法中执行EventBus.getDefault().unregister()。

关于handler的处理方法

对于网上经常说的非静态Handler导致的内存泄漏,我基本没测到过,因为我一直有在onDestroy()方法中执行handler.removeCallbacksAndMessages(null);来清空handler对应的消息队列。而网上更多文章推荐的静态+弱引用,我觉得从逻辑上来看不够针对性,代码编写起来也十分繁杂。因为我基本都是用removeCallbacksAndMessages()方法。具体的测试和对比可以参考这篇文章:Handler 造成 Activity 泄漏,用弱引用真的有用么?

总结

Android的内存泄漏的具体场景可以有千种万种,但核心只有一个,就是Activity执行onDestroy()后还被其他对象持有着,导致JVM通过可达性分析法作出不回收该Activity对象的判断,导致内存泄漏(当然如果你要说你的Activity在onDestroy()后还有特定的存在价值,算不上泄漏;或者你的泄漏对象不是Activity而是Service这些罕见情况,我也是无力反驳的对吧🧐)。
解决Android内存泄漏的核心也只有这个,在onDestroy()确保这个Activity对象不再被其他对象引用着。这样就确保不会发生内存泄漏了,最起码按Leak Canary对内存泄漏的定义是这样的。

当然以上也只是理论上的理想情况🤣实际上国产的安卓机还有各种坑。我手上的华为Mate,EMUI版本8.0.0,Android版本8.0,就经常检测到一个什么mLastClickView的内存泄漏,我Google了一下,应该是华为系统的bug,其他国产定制手机也遇到过类似的奇奇怪怪的内存泄漏。对于这种系统级别的bug导致的内存泄漏,我们也无能为力的~我们作为应用开发者,在应用层上在自己的项目中确保不产生内存泄漏就行。

    原文作者:黄光华
    原文地址: https://www.jianshu.com/p/bbc5e6250c5a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞