首先参考一下Google I/O Garbage Collection图片
图片中有黄色及蓝色的区块
可以理解为有爸妈的孩子及孤儿吧
孤儿的部分,由于来历已不可考所以Garbage Collection并没有办法处理它
像这类状况常在开发时因为不容易立即造成当机而被忽略,我本人就是这样,几乎都没有在处理这样的状况
但是当产品规模渐渐变大,孤儿越来越多,会造成被佔用并且无法被回收的记忆体越来越多,而导致OOM
所以必须从平时就养成好习惯别让孤儿产生
这样说起来可能有点抽象,所以就来实做一个练习吧
开始之前要介绍一下我使用的工具
再爬了一些文之后发先这玩意儿满好用的,也很清楚推荐给大家除错的时候可以用
https://github.com/square/leakcanary
练习题
错误版
按照平常的习惯用Singleton的方式建置了一个呼叫API的物件,并且在Activity使用
依照先前的坏习惯,程式写到这就结束了
这时候按下Back离开Activity(onDestroy被呼叫)
在有安装leakcanary情况下,马上就被侦测到问题
也可以很明确的从Stack中看到是错在什么地方
这边用Google I/O的图解释一下
onCreate Activity时reference状态如下(都是黄色的)
MainActivty -> ApiRequest instance -> context
onDestroy Activity时ApiRequest instance中的context瞬间变孤儿
(MainActivty -> ApiRequest instance) x context
我想主要的原因是Activity本身就有回收机制,所以在onCreate初始化的ApiRequest也可以直接被回收机制处理掉
但是在ApiRequest中的物件大概就没这么幸运了
解决的方法
先在ApiRequest物件中加上一个可以配合Activity onDestroy lifecycle的方法
在这方法中处理掉会造成Memory leak的问题
并且在Activity onDestroy时呼叫这个方法
再进行一次测试leakcanary就不再会报出这样的问题
有写错的地方欢迎指正讨论喔