如何使用
第一步:添加依赖
debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.2'
第二步:没了
那他是如何与你的应用程序绑定的
他配置了一个ContentProvider,在 AndroidManifest.xml 中配置, 在 App 打包的时候就会把所有的 AndroidManifest.xml 文件合并到一起。
所以,这个 ContentProvider 就被初始化了。
AndroidManifes.xml 的路径为 :leakcanary-object-watcher-android/src/main/AndroidManifest.xml
<?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.AppWatcherInstaller$MainProcess"
android:authorities="${applicationId}.leakcanary-installer"
android:exported="false"/>
</application>
</manifest>
我们找到这个类,发现是一个封闭类
internal sealed class AppWatcherInstaller : ContentProvider() {
//找到 onCreate 方法
override fun onCreate(): Boolean {
val application = context!!.applicationContext as Application
//主要看这行
InternalAppWatcher.install(application)
return true
}
}
// -> InternalAppWatcher.kt
fun install(application: Application) {
SharkLog.logger = DefaultCanaryLog()
SharkLog.d { "Installing AppWatcher" }
checkMainThread()
if (this::application.isInitialized) {
return
}
InternalAppWatcher.application = application
//上面是一些判断逻辑,主要看下面几行
val configProvider = { AppWatcher.config }
//检测Activity
ActivityDestroyWatcher.install(application, objectWatcher, configProvider)
//检测Fragment
FragmentDestroyWatcher.install(application, objectWatcher, configProvider)
onAppWatcherInstalled(application)
}
//我们来分析Activity的 -> ActivityDestroyWatcher.kt
companion object {
fun install(
application: Application,
objectWatcher: ObjectWatcher,
configProvider: () -> Config
) {
val activityDestroyWatcher =
ActivityDestroyWatcher(objectWatcher, configProvider)
//注册对activity生命周期的监听
application.registerActivityLifecycleCallbacks(activityDestroyWatcher.lifecycleCallbacks)
}
}
private val lifecycleCallbacks =
//利用委托,不实现其他的生命周期方法,只关注其 Destroy 方法
object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
override fun onActivityDestroyed(activity: Activity) {
if (configProvider().watchActivities) {
//跟进这个方法继续看
objectWatcher.watch(
activity, "${activity::class.java.name} received Activity#onDestroy() callback"
)
}
}
}
**
* Watches the provided [watchedObject].
*
* @param description Describes why the object is watched.
*/
@Synchronized fun watch(
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"
}
//把当前这个 reference 加到 map 里面
watchedObjects[key] = reference
checkRetainedExecutor.execute {
//继续看这个方法
moveToRetained(key)
}
}
//这个方法叫 移除弱引用可达的对象,tmd我也不知道啥意思
//说人话: 就是从这个queue中取这个 ref ,如果能取到,说明这个 ref 将要被 GC,这个时候就没有发生泄漏,我们就可以在 watchedObjects 中删除掉这个 key。
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 {
//注意这个 queue -> private val queue = ReferenceQueue<Any>()
ref = queue.poll() as KeyedWeakReference?
if (ref != null) {
//如果能取到,就在这个 map 中移除掉这个key -> private val watchedObjects = mutableMapOf<String, KeyedWeakReference>()
// value 其实就是引用的 activity
watchedObjects.remove(ref.key)
}
} while (ref != null)
}
@Synchronized private fun moveToRetained(key: String) {
//如果已经在queue中能取到,说明可以进行GC了,就在 watchedObjects 中移除,我们就不需要再观察了。
removeWeaklyReachableObjects()
val retainedRef = watchedObjects[key]
if (retainedRef != null) {
//这个时候,如果发现 ref 没有被删除,这就说明发生了泄漏
retainedRef.retainedUptimeMillis = clock.uptimeMillis()
onObjectRetainedListeners.forEach { it.onObjectRetained() }
}
}
困了,就先这样。