LeakCanary如何监听Service、Root View销毁时机?

本篇文章讲解LeakCanary如何监听Service、Root View销毁时机并添加到泄漏监听中的。

监听Service销毁时机

我先说下大体的思路:

  1. 首先我们反射ActivityThread中属性名为mH的Handler对象,这个对象大家都是很熟悉,AMS通过应用侧的ApplicationThread发送调度通知,然后ApplicationThread将调度操作封装成Meesage并通过这个名为mH的Handler发送出去,然后最终Message被执行,里面调度Acitivity、Service生命周期的操作也自然会被执行了;

  1. 然后我们反射给mH的属性mCallback赋值,这个属性对象在处理Message的时机是优先于Handler的handleMessage()方法的,所以我们在这个mCallback是可以监听到Service生命周期调度的。

通过以上方式我们监听到Messagewhat==116时,就代表Service将执行onDestroy()生命周期,并将这个Service弱引用保存起来;

  1. 问题来了,Service的onDestory()什么时候执行完毕呢,这个时候我们就要从源码中寻找解决答案了。看下ActivityThread源码,最终会在handleStopService()执行Service的onDestroy()方法:

可以看到,Service的onDestroy()执行完毕后,就会调用IActivityManager这个Binder对象的方法serviceDoneExecuting()通知AMS。看到这里,是不是明白了怎么做。

  1. 我们可以通过反射动态代理掉应用侧的IActivityManager这个Binder对象,并重写其serviceDoneExecuting()方法完成Service的onDestroy()执行完毕的监听。LeakCanary中的源码就是这么做的:
  • 首先动态代理创建一个实现了IActivityManager接口的对象,这个代理对象里面就会判断当前的方法为serviceDoneExecuting时,代表当前的Service的onDestory()生命周期已经执行完毕,可以对当前Service添加内存泄漏监听了
    =

  • 然后将当前ActivityManager对象中原有的IActivityManager这个binder对象替换成我们上面动态代理创建的IActivityManager对象

  • 通过以上方式,我们就实现了Service销毁时机的监听,并添加到内存泄漏的监听中。

监听Root View销毁时机

这里监听Root View之一就是监听Dialog的根View是否发生了内存泄漏。看下LeakCanary核心代码是如何处理的:

很熟悉的代码,就是拿到Dialog的根View,然后调用addOnAttchStateChangeListener添加监听,并在监听实现类中重写onViewDetachedFromWindow()方法,当根View不可见的时候,就会触发该方法的执行。

至于LeakCanary是怎么统一拿到业务层的Dialog的根View布局的,笔者看了源码也不是很清楚怎么实现的,实现的代码如下,底层的原理就不懂了:

不过上面这种监听Dialog的根View内存泄漏的方式有一个非常严重的问题:

大家在写代码的过程中可能会有一个习惯,在某个类中创建一个全局的成员变量持有这个Dialog,这样方便在全局调用其show()或者dismiss()方法。

这样就会导致Dialog执行dismiss()方法关闭弹窗时,Dialog被类的全局变量持有,而Dialog又会持有其根View,所以根View不会被回收销毁的。而这个时候根View已经从屏幕上消息不可见,就会回调onViewDetachedFromWindow()方法,将根View添加到LeakCanary的销毁监听中,这样就会百分之百导致内存泄漏。

上面这种情况下,本身业务类中的某个全局成员属性持有Dialog的行为是很正常的,所以就只能LeakCanary去兼容处理了:

可以看到LeakCanary能不能检测Dialog的Root View(根View)是有开关可以控制的,如果我们项目中存在业务类全局持有Dialog的行为,就可以在xml中将leak_canary_watcher_watch_dismissed_dialogs设置为false即可,这样LeakCanary就不会检测Dialog的Root View销毁了。

作者:长安皈故里
链接:https://juejin.cn/post/7114683266170372104
更多Android相关知识、学习笔记、视频资料详情可扫描下方二维码领取!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值