LeakCanary ,直译为泄露的金丝雀,名称来源于一个关于金丝雀的故事。在17世纪的英国,煤矿业还没发展出检测瓦斯泄露探测仪,于是矿工们在下矿井时就带一只金丝雀。金丝雀对瓦斯及其敏感,稍微有瓦斯泄漏,它就会停止歌唱,浓度再高一些,金丝雀就会直接中毒身亡。而这时候,人比他皮糙肉厚一些,人类迟钝的感觉是完全没有意识到瓦斯的存在的。如果此时再不及时逃出矿坑,那么死的就是矿工了,正式借用了这层寓意,才起了LeakCanary这个名字,正如这个组件的功能一样,这个组件意在像检测瓦斯泄露的金丝雀一样,在危险发生之前,提前的检测内存泄露。
LeakCanary是一个专门针对于Android的 内存泄露检测的库,LeakCanary通过对Android框架内部知识的了解,监听Activity与fragment的生命周期,实现对Activity,Fragment,Fragment View和ViewModel实例的内存泄露的监控,被监控的对象,在垃圾回收的5秒后没有回收掉的话,这个对象就会被认为是被保留了,和潜在内存泄露的
起始版本,仅Activity的监控
1.6.1 版本,加入了对Fragment的监控
1.6.2版本,加入了对Fragment view的监控
2.2版本,加入了对ViewModel的监控
正如功能简介中描述的一样,LeakCanary通过对Android框架内部知识的了解,来实现的泄露监控,从发展史上我们也能看到,随着对android代码了解的加深,其检测能力,也逐渐丰富
https://square.github.io/leakcanary/fundamentals/
dependencies {
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.3'
}
通过Logcat 查看 输出打印 D LeakCanary: LeakCanary is running and ready to detect leaks
当按照接入方式接入成后,正常操作APP即可,当有内存泄露发生时,会在在桌面生成内存泄露的图标,点击进入后可以查看相关的堆栈信息
1.读懂泄露的信息
├─ :表示一个java对象
│ ↓ :下面一行的对象的一个实例被对当前行的对象引用
**╰→:**表示泄露的对象
2.读取顺序,从泄露的位置向前读
具体实例
阅读源码前,请思考几个问题:
它是如何做到仅一行配置代码就完成监控的
它是在什么时机,去判断是否存在内存泄露的
它是通过什么原理,来判断是否存在内存泄露的
它是如何做到仅一行配置代码就完成监控的
1.ContentProvider的onCreate的调用时机是在application onCreate之前调用的,即在应用启动时,完成了自身代码的调用,降低了接入方在java代码层面上的接入成本
2.通过占位符的方式,简化了接入方在manifest文件上的接入成本
3.debugImplementation 仅在debug模式下生效,降低了使用implementation时需要依赖空包的接入成
它是在什么时机,去判断是否存在内存泄露的
1.Activity:通过在Application中注册registerActivityLifecycleCallbacks绑定Activity生命周期回调,并在onActivityDestroyed回调中监控Activity
2.Fragment:通过在Application中注册registerActivityLifecycleCallbacks绑定Activity生命周期回调,并在onActivityCreated回调中,通过在Activity中注册注册FragmentLifecycleCallbacks回调,并在onFragmentDestroyed回调时,监控fragment
3.Fragment View:通过在Application中注册registerActivityLifecycleCallbacks绑定Activity生命周期回调,并在onActivityCreated回调中,通过在Activity中注册注册FragmentLifecycleCallbacks回调,并在onFragmentViewDestroyed回调中监控Fragment View
4.ViewModel:针对AndroidX库中的Activity,对于Activit,在onActivityCreated回调中注册监听,对于Fragment,在onFragmentCreated回调中注册监听,,,在ViewModel的onCleared回调中监控ViewModel
它是通过什么原理,来判断是否存在内存泄露的
是利用了WeakRefrence + RefrenceQueue的机制(仅被弱引用持有的对象,当对象被回收时,会存入到引用队列中),从引用队列中不断的获取对象,将已确认被GC的对象剔除,剩余未被回收的对象则定义为可能泄露的对象,当达到一定的判断条件时,通知用户内存泄露
AppWatcher.objectWatcher.watch(myDetachedView, “View was detached”)
阅读完源码,说下个人对下面这个方法的理解。android是在不断发展完善的,就像viewmodel一样,是新增的检测类型,这个方法的作用,就是当我们自定义了一些存在生命周期的东西时,在改对象生命周期结束的时候,可以手动的调用这个方法,来监控自定义对象的生命周期