面试系列“讲一下吧”之 LeakCanary

如何使用

第一步:添加依赖

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() }
  }
}




困了,就先这样。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章