背景
- 2.0版本相对于1.x版本,全部用的kotlin编写
- 在application类中,不需要install()方法,监听的是content provider的启动即可
启动监听
1、监听ContentProvider的启动即可
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="com.squareup.leakcanary.objectwatcher"
>
<application>
<provider
android:name="leakcanary.internal.MainProcessAppWatcherInstaller"
android:authorities="${applicationId}.leakcanary-installer"
android:enabled="@bool/leak_canary_watcher_auto_install"
android:exported="false"/>
</application>
</manifest>
internal class MainProcessAppWatcherInstaller : ContentProvider() {
override fun onCreate(): Boolean {
val application = context!!.applicationContext as Application
静默初始化
AppWatcher.manualInstall(application)
return true
}
}
流程分析
1、在AppWatcher类的manualInstall()方法中,调用LeakCanaryDelegate.loadLeakCanary(),初始化它
object AppWatcher {
fun manualInstall(
application: Application,
retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
) {
...
LeakCanaryDelegate.loadLeakCanary(application)
这里完成了ActivityWatcher的install()注册
watchersToInstall.forEach {
it.install()
}
...
}
}
2、通过反射实例化对象,并且通过get(null) as (Application)调用它的invoke方法
internal object LeakCanaryDelegate {
@Suppress("UNCHECKED_CAST")
val loadLeakCanary by lazy {
try {
实例化对象
val leakCanaryListener = Class.forName("leakcanary.internal.InternalLeakCanary")
leakCanaryListener.getDeclaredField("INSTANCE")
.get(null) as (Application) -> Unit
} catch (ignored: Throwable) {
NoLeakCanary
}
}
object NoLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
override fun invoke(application: Application) {
}
override fun onObjectRetained() {
}
}
}
我们创建InternalAppWatcher时init方法就会调用,onAppWatcherInstalled是kotlin中invoke约定的应用可以将invoke函数的lambda表达式赋值给一个变量,
Kotlin的约定有很多种,而比如使用便捷的get操作,以及重载运算符等等,invoke约定也仅仅是一种约定而已;
我们可以把lambda表达式或者函数直接保存在一个变量中,然后就像执行函数一样直接执行这个变量,
这样的变量通常声明的时候都被我们赋值了已经直接定义好的lambda,或者通过成员引用而获取到的函数;
但是别忘了,在面向对象编程中,一个对象在通常情况下都有自己对应的类,那我们能不能定义一个类,
然后通过构造方法来产生一个对象,然后直接执行它呢?这正是invoke约定发挥作用的地方。
我们只需要在一个类中使用operator来修饰invoke函数,这样的类的对象就可以直接像一个保存lambda表达式的变量一样直接调用,而调用后执行的函数就是invoke函数。
我们还有另一种方式来实现可调用的对象,即让类继承自函数类型,然后重写invoke方法。
————————————————
版权声明:本文为CSDN博主「Darksiderl」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011148116/article/details/106762665/
3、在AppWatcher的构造函数中appDefaultWatchers(application),初始化了几个观察对象
object AppWatcher {
构造函数
fun manualInstall(
application: Application,
retainedDelayMillis: Long = TimeUnit.SECONDS.toMillis(5),
watchersToInstall: List<InstallableWatcher> = appDefaultWatchers(application)
) {
...
...
}
多个观察者
fun appDefaultWatchers(
application: Application,
reachabilityWatcher: ReachabilityWatcher = objectWatcher
): List<InstallableWatcher> {
return listOf(
ActivityWatcher(application, reachabilityWatcher),
FragmentAndViewModelWatcher(application, reachabilityWatcher),
RootViewWatcher(reachabilityWatcher),
ServiceWatcher(reachabilityWatcher)
)
}
}
我们找到其中一个ActivityWatcher()
class ActivityWatcher(
private val application: Application,
private val reachabilityWatcher: ReachabilityWatcher
) : InstallableWatcher {
private val lifecycleCallbacks =
object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
override fun onActivityDestroyed(activity: Activity) {
reachabilityWatcher.expectWeaklyReachable(
activity, "${activity::class.java.name} received Activity#onDestroy() callback"
)
}
}
override fun install() {
application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
}
override fun uninstall() {
application.unregisterActivityLifecycleCallbacks(lifecycleCallbacks)
}
}
4、在onActivityDestroyed触发的时候会调用reachabilityWatcher.expectWeaklyReachable()方法,reachabilityWatcher的类型是ReachabilityWatcher,在构造方法传入
fun appDefaultWatchers(
application: Application,
reachabilityWatcher: ReachabilityWatcher = objectWatcher
): List<InstallableWatcher> {
return listOf(
ActivityWatcher(application, reachabilityWatcher),
...
)
}
由此可知道reachabilityWatcher是objectWatcher传入的,它是一个ObjectWatcher类型
val objectWatcher = ObjectWatcher(
clock = { SystemClock.uptimeMillis() },
checkRetainedExecutor = {
check(isInstalled) {
"AppWatcher not installed"
}
mainHandler.postDelayed(it, retainedDelayMillis)
},
isEnabled = { true }
)
5、reachabilityWatcher.expectWeaklyReachable()实际调用的就是在ObjectWatcher.expectWeaklyReachable()方法
class ObjectWatcher constructor() : ReachabilityWatcher {
@Synchronized override fun expectWeaklyReachable(
watchedObject: Any,
description: String
) {
if (!isEnabled()) {
return
}
removeWeaklyReachableObjects()
val key = UUID.randomUUID()
.toString()
val watchUptimeMillis = clock.uptimeMillis()
val reference =
KeyedWeakReference(watchedObject, key, description, watchUptimeMillis, queue)
SharkLog.d {
"Watching " +
(if (watchedObject is Class<*>) watchedObject.toString() else "instance of ${watchedObject.javaClass.name}") +
(if (description.isNotEmpty()) " ($description)" else "") +
" with key $key"
}
watchedObjects[key] = reference
checkRetainedExecutor.execute {
moveToRetained(key)
}
}
}
需要了解知识点:gc后,软引用可以和一个引用队列(ReferenceQueue)联合使用,如果软引用所引用的对象被垃圾回收器回收,Java虚拟机就会把这个软引用加入到与之关联的引用队列中。
- removeWeaklyReachableObjects() 方法这个数据被回收了(不为空),那么从被观察的集合中移除
注意KeyedWeakReference是WeakReference类型,可以传入一个队列监听它是否被回收,参考WeakReference类的定义构造函数
class KeyedWeakReference(
referent: Any,
val key: String,
val description: String,
val watchUptimeMillis: Long,
referenceQueue: ReferenceQueue<Any>
) : WeakReference<Any>(
referent, referenceQueue
) {}
private fun removeWeaklyReachableObjects() {
// WeakReferences are enqueued as soon as the object to which they point to becomes weakly
// reachable. This is before finalization or garbage collection has actually happened.
var ref: KeyedWeakReference?
do {
ref = queue.poll() as KeyedWeakReference?
if (ref != null) {
watchedObjects.remove(ref.key)
}
} while (ref != null)
}
- moveToRetained(key)做一次gc操作
@Synchronized private fun moveToRetained(key: String) {
removeWeaklyReachableObjects()
val retainedRef = watchedObjects[key]
if (retainedRef != null) {
retainedRef.retainedUptimeMillis = clock.uptimeMillis()
onObjectRetainedListeners.forEach { it.onObjectRetained() }
}
}
private val onObjectRetainedListeners = mutableSetOf<OnObjectRetainedListener>()
@Synchronized fun addOnObjectRetainedListener(listener: OnObjectRetainedListener) {
onObjectRetainedListeners.add(listener)
}
6、回到之前AppWatcher注册环节
object AppWatcher {
fun manualInstall() {
...
LeakCanaryDelegate.loadLeakCanary(application)
...
}
}
在之前实例化InternalLeakCanary后,调用了invoke()方法,
internal object LeakCanaryDelegate {
@Suppress("UNCHECKED_CAST")
val loadLeakCanary by lazy {
实例化对象
val leakCanaryListener = Class.forName("leakcanary.internal.InternalLeakCanary")
leakCanaryListener.getDeclaredField("INSTANCE")
.get(null) as (Application) -> Unit
}
调用invoke方法
object NoLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
override fun invoke(application: Application) {
}
}
}
这里完成了OnObjectRetainedListener的注册
internal object InternalLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
override fun invoke(application: Application) {
...
AppWatcher.objectWatcher.addOnObjectRetainedListener(this)
...
}
}
7、所以我们看InternalLeakCanary类的onObjectRetained()方法
override fun onObjectRetained() = scheduleRetainedObjectCheck()
fun scheduleRetainedObjectCheck() {
if (this::heapDumpTrigger.isInitialized) {
heapDumpTrigger.scheduleRetainedObjectCheck()
}
}
8、在HeapDumpTrigger类的,触发一次gc,并且下次堆栈信息
internal class HeapDumpTrigger() {
fun scheduleRetainedObjectCheck(
delayMillis: Long = 0L
) {
...
checkRetainedObjects()
...
}
private fun checkRetainedObjects() {
...
触发gc
gcTrigger.runGc()
...
下载堆栈信息
dumpHeap()
}
}
9、dumpHeap()方法中
private fun dumpHeap(
retainedReferenceCount: Int,
retry: Boolean,
reason: String
) {
...
configProvider().heapDumper.dumpHeap(heapDumpFile)
...
}
internal object InternalLeakCanary : (Application) -> Unit, OnObjectRetainedListener {
override fun invoke(application: Application) {
...
val configProvider = { LeakCanary.config }
heapDumpTrigger = HeapDumpTrigger(
application, backgroundHandler, AppWatcher.objectWatcher, gcTrigger,
configProvider
)
...
}
}
LeakCanary.config = LeakCanary.config.copy(dumpHeap = LeakCanary.config.dumpHeap)
object LeakCanary {
/**
* The current LeakCanary configuration. Can be updated at any time, usually by replacing it with
* a mutated copy, e.g.:
*
* ```kotlin
* LeakCanary.config = LeakCanary.config.copy(retainedVisibleThreshold = 3)
* ```
*
* In Java, use [LeakCanary.Config.Builder] instead:
* ```java
* LeakCanary.Config config = LeakCanary.getConfig().newBuilder()
* .retainedVisibleThreshold(3)
* .build();
* LeakCanary.setConfig(config);
* ```
*/
@JvmStatic @Volatile
var config: Config = Config()
set(newConfig) {
val previousConfig = field
field = newConfig
HeapDumpControl.updateICanHasHeapInBackground()
}
}