当前位置:网站首页>LeakCanary如何监听Service、Root View销毁时机?
LeakCanary如何监听Service、Root View销毁时机?
2022-08-01 10:15:00 【大鱼Ss】
本篇文章讲解LeakCanary如何监听Service、Root View销毁时机并添加到泄漏监听中的。
监听Service
销毁时机
我先说下大体的思路:
- 首先我们反射
ActivityThread
中属性名为mH
的Handler对象,这个对象大家都是很熟悉,AMS通过应用侧的ApplicationThread
发送调度通知,然后ApplicationThread将调度操作封装成Meesage
并通过这个名为mH的Handler发送出去,然后最终Message被执行,里面调度Acitivity、Service生命周期的操作也自然会被执行了;
- 然后我们反射给mH的属性
mCallback
赋值,这个属性对象在处理Message的时机是优先于Handler的handleMessage()
方法的,所以我们在这个mCallback是可以监听到Service生命周期调度的。
通过以上方式我们监听到Message
的what==116
时,就代表Service
将执行onDestroy()
生命周期,并将这个Service弱引用保存起来;
- 问题来了,Service的
onDestory()
什么时候执行完毕呢,这个时候我们就要从源码中寻找解决答案了。看下ActivityThread源码,最终会在handleStopService()
执行Service的onDestroy()方法:
可以看到,Service的onDestroy()
执行完毕后,就会调用IActivityManager
这个Binder
对象的方法serviceDoneExecuting()
通知AMS
。看到这里,是不是明白了怎么做。
- 我们可以通过反射动态代理掉应用侧的
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相关知识、学习笔记、视频资料详情可扫描下方二维码领取!!
边栏推荐
- MFC实现交通图导航系统
- 小程序毕设作品之微信美食菜谱小程序毕业设计成品(3)后台功能
- VS“无法查找或打开PDB文件”是怎么回事?如何解决
- Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (3) Background Functions
- redis
- 阿里腾讯面试一二
- slice、splice、split傻傻分不清
- 广域铭岛入选2022年重庆市数字经济产业发展试点示范项目名单
- 【cartographer ros】十: 延时和误差分析
- MFC implementation road map navigation system
猜你喜欢
AI篮球裁判火了,走步算得特别准,就问哈登慌不慌
IntellJ IDEA如何显示换行符(line endings)
The use of scrapy crawler framework
基于CAP组件实现补偿事务与消息幂等性
小程序毕设作品之微信美食菜谱小程序毕业设计成品(4)开题报告
gc的意义和触发条件
CTFshow,命令执行:web31
How programmers learn open source projects, this article tells you
C language game - minesweeper
Enterprise WeChat group: robot timing reminder function database configuration
随机推荐
Mysql索引相关的知识复盘一
周鸿祎称微软抄袭 360 安全模式后发文否认;英特尔CEO基辛格回应市值被AMD超越:股价下跌是咎由自取|极客头条
PDMan-domestic free general database modeling tool (minimalist, beautiful)
Mini Program Graduation Works WeChat Food Recipes Mini Program Graduation Design Finished Products (3) Background Functions
回归预测 | MATLAB实现RNN循环神经网络多输入单输出数据预测
分类预测 | MATLAB实现1-DCNN一维卷积神经网络分类预测
如何在IntellJ IDEA中批量修改文件换行符
Google Earth Engine——给影像添加一个属性对于单景的时间序列并返回影像
【软件架构模式】MVVM模式和MVC模式区别
[Cloud Residency Co-Creation] Huawei Cloud Global Scheduling Technology and Practice of Distributed Technology
50.【Application of dynamic two-dimensional array】
For small applications, which database is better to use?
notes....
Node's traditional and advanced practices for formatting time (moment)
玻璃拟态(Glassmorphism)设计风格
SAP ABAP OData 服务如何支持 $orderby (排序)操作试读版
July 31, 2022 -- Take your first steps with C# -- Use arrays and foreach statements in C# to store and iterate through sequences of data
Drawing arrows of WPF screenshot control (5) "Imitation WeChat"
ClickHouse入门介绍与其特性
mysql在cmd的登录及数据库与表的基本操作