如何使用
第一步:添加依賴
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() }
}
}
困了,就先這樣。