Kotlin 干掉接口需要强制实现的方法

假如我有这样一个需求:我需要记录应用中所有存活的 Activity,那么我的代码就会像以下代码那么写。

class App : Application() {
    
    private val activeActivities: ArrayList<Activity> = ArrayList()
    
    private val activityLifecycleCallback: ActivityLifecycleCallbacks = object : ActivityLifecycleCallbacks {
        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            activeActivities.add(activity)
        }

        override fun onActivityStarted(activity: Activity) {
            
        }

        override fun onActivityResumed(activity: Activity) {
            
        }

        override fun onActivityPaused(activity: Activity) {
            
        }

        override fun onActivityStopped(activity: Activity) {
            
        }

        override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
            
        }

        override fun onActivityDestroyed(activity: Activity) {
            activeActivities.remove(activity)
        }

    }
    
    override fun onCreate() {
        super.onCreate()
        registerActivityLifecycleCallbacks(activityLifecycleCallback)
    }
}

我相信很多的人都和我一样写过上面的代码,代码的实现没有什么问题,也没有什么性能问题,就是源码读起来非常的蛋疼,我们其实只需要 ActivityLifecycleCallbacks 中的两个回调方法,其他的方法我们其实不需要,由于这是接口的定义,所以我们必须实现,但是方法中又是空的,什么都没有干,所以上面的代码的可阅读性就非常差,如果我们能够把 ActivityLifecycleCallbacks 所有的空实现方法就干掉就清爽了。

那么我们真的可以干掉这些 Callback 恶心的空实现方法吗?在我看到 LeakCanary 的源码之前,我也认为没有好的方法把它干掉。我就通过 LeakCanary 的实现方式来改造上面的代码:

class App : Application() {

    private val activeActivities: ArrayList<Activity> = ArrayList()

    private val activityLifecycleCallback: ActivityLifecycleCallbacks = object : ActivityLifecycleCallbacks by noOpDelegate() {
        override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
            activeActivities.add(activity)
        }
        override fun onActivityDestroyed(activity: Activity) {
            activeActivities.remove(activity)
        }
    }

    override fun onCreate() {
        super.onCreate()
        registerActivityLifecycleCallbacks(activityLifecycleCallback)
    }
}

哈哈,上面的代码是不是瞬间清爽了,上面的代码是通过 Java 中的动态代理和 Kotlin 中的代理/委托实现的。不熟悉 Java 动态代理的同学去网上找找相关的资料,如果不清楚 Kotlin 代理/委托实现的原理可以看看我之前的文章: 基于字节码指令分析 Kotlin 代理

那么我们就看看这个充满魔法的 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
}

是不是又震惊了,哈哈,代码怎么这么少。牛逼的操作往往都是这么朴实无华。就是通过 Java 动态代理在运行时生成了一个实现了对应接口的对象,对象方法实现的 InvocationHandler 是一个空实现,啥也没有干。

所以调用 noOpDelegate() 方法就得到了一个实现了对应接口的对象,不过这个对象调用所有方法都没有反应。

然后我们再把上面生成的空实现对象再去代理我们的对象,这样就得到了上面的效果,Kotlin 中的被代理的对象可以选择重写需要的方法,这就达到了我们上面的效果,只需要重写我们需要的回调方法。

Kotlin 的对象代理/委托在开发中也用得非常多,也非常好用,Kotlin 官方也提供了很多这样的方法,比如我想要 Activity 实现 CoroutineScope 接口代码就可以像下面这样写:

class MyActivity : Activity(), CoroutineScope by CoroutineScope(Dispatchers.Main) {
    override fun onDestroy() {
        super.onDestroy()
        cancel()
    }
}

Kotlin 干掉接口需要强制实现的方法

作者:Tans5
链接:https://juejin.cn/post/7414310200675074063
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值