巧妙的by noOpDelegate()

509 阅读1分钟

发现

最近在读leakcanary源码时,发现其中有一个比较巧妙的使用by noOpDelegate(),具体代码如下:

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

从代码中可以发现,在实现ActivityLifecycleCallbacks对象表达式时,只实现了onActivityDestroyed(activity: Activity),这是为什么呢?

分析

带着疑问,就去看了noOpDelegate()

internal inline fun <reified T : Any> noOpDelegate(): T = leakcanary.internal.noOpDelegate()

internal inline fun <reified T : Any> noOpDelegate(): T {
  val javaClass = T::class.java
  return Proxy.newProxyInstance(
    javaClass.classLoader, arrayOf(javaClass), NO_OP_HANDLER
  ) as T  
}

private val NO_OP_HANDLER = InvocationHandler { _, _, _ ->
  // no op
}

就可以发现noOpDelegate()返回的是T的动态代理,代理的方法均是空实现。

leakcanary巧妙的结合了动态代理和kolin中的接口委托,object : Application.ActivityLifecycleCallback实现了方法onActivityDestroyed(),其他的方法委托给noDelegate()实现; 使用这样的方式,只需要实现想要实现的方法即可,这样就不用重写接口的每一个方法。

扩展

这样的使用可以用到接口Application.ActivityLifecycleCallbacksAnimator.AnimatorListener

相关知识

内联函数
委托属性