2021-02-03Leakcanary 源码流程<二>(Fragment、ViewModel、RootView、Service 泄露监测)

接上一篇,上一篇分析了Activity的检测,继续来看剩下的Fragment、ViewModel 、RootView、Service的检测

Fragment、ViewModel 泄漏检测

根据上一篇的内容,可以知道Fragment的泄漏检测是在FragmentAndViewModelWatcher中的install方法中注册

  override fun install() {
    //也是调用Application注册监听所有Activity中实现
    application.registerActivityLifecycleCallbacks(lifecycleCallbacks)
  }

继续看lifecycleCallbacks中的处理

  private val lifecycleCallbacks =
    object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
      //监听所有Activity的onCreate方法
      override fun onActivityCreated(
        activity: Activity,
        savedInstanceState: Bundle?
      ) {
        //调用添加的watcher方法
        for (watcher in fragmentDestroyWatchers) {
          watcher(activity)
        }
      }
    }

继续看fragmentDestroyWatchers中怎么添加数据的

  private val fragmentDestroyWatchers: List<(Activity) -> Unit> = run {
    //最后返回的就是这个list,所以看list中添加什么样的数据
    val fragmentDestroyWatchers = mutableListOf<(Activity) -> Unit>()
    //如果sdk版本大于O,也就是26,这里先默认大于,走这个if
    if (SDK_INT >= O) {
      //往list中添加AndroidOFragmentDestroyWatcher对象
      fragmentDestroyWatchers.add(
        AndroidOFragmentDestroyWatcher(reachabilityWatcher)
      )
    }
    //判断是否为androidx 包下面的fragment,
    //如果是就通过反射创建一个AndroidXFragmentDestroyWatcher对象,并添加到list中
    getWatcherIfAvailable(
      ANDROIDX_FRAGMENT_CLASS_NAME,
      ANDROIDX_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
      reachabilityWatcher
    )?.let {
      fragmentDestroyWatchers.add(it)
    }

    //判断是否为v4 包下面的fragment,
    //如果是就通过反射创建一个AndroidSupportFragmentDestroyWatcher对象,并添加到list中
    getWatcherIfAvailable(
      ANDROID_SUPPORT_FRAGMENT_CLASS_NAME,
      ANDROID_SUPPORT_FRAGMENT_DESTROY_WATCHER_CLASS_NAME,
      reachabilityWatcher
    )?.let {
      fragmentDestroyWatchers.add(it)
    }
    fragmentDestroyWatchers
  }

先来看如果sdk大于26的情况下,AndroidOFragmentDestroyWatcher的处理。再添加到list中,在循环中调用watcher(activity)方法时,会走到对应的list中数据的invoke方法中,看AndroidOFragmentDestroyWatcher.invoke()方法

  override fun invoke(activity: Activity) {
    //获取fragmentManager
    val fragmentManager = activity.fragmentManager
    //通过fragmentManager注册fragment生命周期监听
    fragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
  }

通过fragmentManager注册fragment生命周期监听,看对应监听方法

  private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {
    //监听fragment的ViewDestroyed方法,就是fragment中View销毁时回调
    override fun onFragmentViewDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      //获取view
      val view = fragment.view
      if (view != null) {
        //如果view不为null,进入观察方法中
        reachabilityWatcher.expectWeaklyReachable(
          view, "${fragment::class.java.name} received Fragment#onDestroyView() callback " +
          "(references to its views should be cleared to prevent leaks)"
        )
      }
    }
    //监听fragment的Destroyed方法
    override fun onFragmentDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      //观察这个fragment是否回收
      reachabilityWatcher.expectWeaklyReachable(
        fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
      )
    }
  }

通过onFragmentViewDestroyed和onFragmentDestroyed方法分别监听fragment中view和自身的回收情况来判断是否出现泄漏,其中expectWeaklyReachable方法在上一篇已经介绍。

继续往下看,如果使用的androidx包下的framgent,进入AndroidXFragmentDestroyWatcher中invoke方法

  override fun invoke(activity: Activity) {
    //判断当前activity是否为FragmentActivity
    if (activity is FragmentActivity) {
      //获取supportFragmentManager
      val supportFragmentManager = activity.supportFragmentManager
      //同样通过supportFragmentManager注册framgent监听
      supportFragmentManager.registerFragmentLifecycleCallbacks(fragmentLifecycleCallbacks, true)
      //ViewModel监听
      ViewModelClearedWatcher.install(activity, reachabilityWatcher)
    }
  }

先来看framgent的监听,也是走到对应的监听方法中

  private val fragmentLifecycleCallbacks = object : FragmentManager.FragmentLifecycleCallbacks() {

    override fun onFragmentCreated(
      fm: FragmentManager,
      fragment: Fragment,
      savedInstanceState: Bundle?
    ) {
      //注册framgent中的ViewModel肩痛
      ViewModelClearedWatcher.install(fragment, reachabilityWatcher)
    }

    //同上,监听fragment的view
    override fun onFragmentViewDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      val view = fragment.view
      if (view != null) {
        reachabilityWatcher.expectWeaklyReachable(
          view, "${fragment::class.java.name} received Fragment#onDestroyView() callback " +
          "(references to its views should be cleared to prevent leaks)"
        )
      }
    }
    //监听framgent的回收
    override fun onFragmentDestroyed(
      fm: FragmentManager,
      fragment: Fragment
    ) {
      reachabilityWatcher.expectWeaklyReachable(
        fragment, "${fragment::class.java.name} received Fragment#onDestroy() callback"
      )
    }
  }

framgnet的监听和前面O的监听一样,主要就是增加了一个ViewModel的监听,接下来看ViewModel的监听,走到ViewModelClearedWatcher.install方法中

    fun install(
      storeOwner: ViewModelStoreOwner,
      reachabilityWatcher: ReachabilityWatcher
    ) {
      //通过provider创建一个ViewModelClearedWatcher的ViewModel对象
      val provider = ViewModelProvider(storeOwner, object : Factory {
        @Suppress("UNCHECKED_CAST")
        override fun  create(modelClass: Class): T =
          ViewModelClearedWatcher(storeOwner, reachabilityWatcher) as T
      })
      provider.get(ViewModelClearedWatcher::class.java)
    }
  }

上面代码就是创建一个ViewModelClearedWatcher对象,并将它和activity或fragment关联起来,当ViewMode回收时,会调用onCleared方法,所以走到ViewModelClearedWatcher的onCleared方法中

  private val viewModelMap: Map?

  init {
     //init 方法在初始化的时候就会调用,在这里获取缓存ViewModel的mMap对象
    // We could call ViewModelStore#keys with a package spy in androidx.lifecycle instead,
    // however that was added in 2.1.0 and we support AndroidX first stable release. viewmodel-2.0.0
    // does not have ViewModelStore#keys. All versions currently have the mMap field.
    viewModelMap = try {
      val mMapField = ViewModelStore::class.java.getDeclaredField("mMap")
      mMapField.isAccessible = true
      @Suppress("UNCHECKED_CAST")
      mMapField[storeOwner.viewModelStore] as Map
    } catch (ignored: Exception) {
      null
    }
  }

  override fun onCleared() {
    //循环mMap中的数据,判断ViewModel是否出现泄漏
    viewModelMap?.values?.forEach { viewModel ->
      reachabilityWatcher.expectWeaklyReachable(
        viewModel, "${viewModel::class.java.name} received ViewModel#onCleared() callback"
      )
    }
  }

RootView泄漏检测

走到RootView泄漏检测的类中,也就是RootViewWatcher的install方法

  override fun install() {
    //如果sdk版本小雨19,直接返回,不检测
    if (Build.VERSION.SDK_INT < 19) {
      return
    }
    //这一段代码是,通过反射获取mView,拦截mView.add()方法,每当调用add方法是,就会走自身的onRootViewAdded方法,并将这个view传过去
    swapViewManagerGlobalMViews { mViews ->
      object : ArrayList(mViews) {
        override fun add(element: View): Boolean {
          onRootViewAdded(element)
          return super.add(element)
        }
      }
    }
  }

  //反射获取WindowManagerGlobal中的mView
  @SuppressLint("PrivateApi")
  @Suppress("FunctionName")
  private fun swapViewManagerGlobalMViews(swap: (ArrayList) -> ArrayList) {
    try {
      val windowManagerGlobalClass = Class.forName("android.view.WindowManagerGlobal")
      val windowManagerGlobalInstance =
        windowManagerGlobalClass.getDeclaredMethod("getInstance").invoke(null)

      val mViewsField =
        windowManagerGlobalClass.getDeclaredField("mViews").apply { isAccessible = true }

      @Suppress("UNCHECKED_CAST")
      val mViews = mViewsField[windowManagerGlobalInstance] as ArrayList

      mViewsField[windowManagerGlobalInstance] = swap(mViews)
    } catch (ignored: Throwable) {
      SharkLog.d(ignored) { "Could not watch detached root views" }
    }
  }

根据上面代码,可以知道,每当创建一个view并添加到mView中时,就会调用onRootViewAdded方法

  private fun onRootViewAdded(rootView: View) {
    //注册view的状态监听
    rootView.addOnAttachStateChangeListener(object : OnAttachStateChangeListener {

      val watchDetachedView = Runnable {
        //执行view的泄露检测
        reachabilityWatcher.expectWeaklyReachable(
          rootView, "${rootView::class.java.name} received View#onDetachedFromWindow() callback"
        )
      }

      override fun onViewAttachedToWindow(v: View) {
        //添加到Window时,移除run
        mainHandler.removeCallbacks(watchDetachedView)
      }

      override fun onViewDetachedFromWindow(v: View) {
        //当view在window中销毁时,执行run
        mainHandler.post(watchDetachedView)
      }
    })
  }

总结一下view的泄漏检测,通过反射的方式获取mView,hook add 方法,每次调用add方法时,执行onRootViewAdded方法,通过注册view的状态变化,来观察view的泄漏

Service泄漏检测

走到ServiceWatcher. install方法中

  override fun install() {
    //做一些检查
    checkMainThread()
    check(uninstallActivityThreadHandlerCallback == null) {
      "ServiceWatcher already installed"
    }
    check(uninstallActivityManager == null) {
      "ServiceWatcher already installed"
    }
    try {
      //和前面hook mView差不多,不过是hook mH 的callback
      swapActivityThreadHandlerCallback { mCallback ->
        uninstallActivityThreadHandlerCallback = {
          swapActivityThreadHandlerCallback {
            mCallback
          }
        }
        Handler.Callback { msg ->
          //当调用了service 的onDestroy时
          if (msg.what == STOP_SERVICE) {
            val key = msg.obj as IBinder
            activityThreadServices[key]?.let {
             //将这个service通过弱引用的方式保存到servicesToBeDestroyed中
              onServicePreDestroy(key, it)
            }
          }
          mCallback?.handleMessage(msg) ?: false
        }
      }
      //继续hook,这里hook的是ActivityManagerService
      swapActivityManager { activityManagerInterface, activityManagerInstance ->
        uninstallActivityManager = {
          swapActivityManager { _, _ ->
            activityManagerInstance
          }
        }

        //动态代理的方式
        Proxy.newProxyInstance(
          activityManagerInterface.classLoader, arrayOf(activityManagerInterface)
        ) { _, method, args ->
          //当调用serviceDoneExecuting方法时,观察这个service的泄漏情况
          if (METHOD_SERVICE_DONE_EXECUTING == method.name) {
            //通过token获取service
            val token = args!![0] as IBinder
            if (servicesToBeDestroyed.containsKey(token)) {
              //观察service泄漏情况
              onServiceDestroyed(token)
            }
          }
          try {
            if (args == null) {
              method.invoke(activityManagerInstance)
            } else {
              method.invoke(activityManagerInstance, *args)
            }
          } catch (invocationException: InvocationTargetException) {
            throw invocationException.targetException
          }
        }
      }
    } catch (ignored: Throwable) {
      SharkLog.d(ignored) { "Could not watch destroyed services" }
    }
  }

最后走到onServiceDestroyed方法中

  private fun onServiceDestroyed(token: IBinder) {
    servicesToBeDestroyed.remove(token)?.also { serviceWeakReference ->
      serviceWeakReference.get()?.let { service ->
        //检测service的泄漏情况
        reachabilityWatcher.expectWeaklyReachable(
          service, "${service::class.java.name} received Service#onDestroy() callback"
        )
      }
    }
  }

总结一些service的泄漏检测,通过hook mH回调的service的onDestroy的方法,将该service保存到activityThreadServices。hook AMS,当调用了serviceDoneExecuting方法时,判断service是否出现泄漏。

你可能感兴趣的:(2021-02-03Leakcanary 源码流程<二>(Fragment、ViewModel、RootView、Service 泄露监测))