Kotlin 优雅的接口实现
1. 日常遇到的冗余的接口方法实现
日常开发中,经常会要实现接口,但是很多场景中,只需要用到其中一两个方法,例如 ActivityLifecycleCallbacks
,它有很多个接口需要实现,但是很多时候我们只需要用到其中的一两个
val myActivityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks {
/**
* 例如我们只需要监听 Activity 的创建和销毁,那么 onActivityStarted, onActivityResumed, onActivityPaused
* onActivityStopped,onActivityStopped,onActivitySaveInstanceState 这 6 个方法是完全没必要是做实现的,
* 即使是空实现
*/
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
TODO("Not yet implemented")
}
override fun onActivityStarted(activity: Activity) {
TODO("Not yet implemented")
}
override fun onActivityResumed(activity: Activity) {
TODO("Not yet implemented")
}
override fun onActivityPaused(activity: Activity) {
TODO("Not yet implemented")
}
override fun onActivityStopped(activity: Activity) {
TODO("Not yet implemented")
}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {
TODO("Not yet implemented")
}
override fun onActivityDestroyed(activity: Activity) {
TODO("Not yet implemented")
}
}
如果有多个不同业务需要实现这个接口,就这样很容易产生代码冗余。有没有一种优雅的方式,只需要实现自己需要的方法而不再需要去关注其他方法?有的,那就是利用 Java 的动态代理和 kotlin 的委托模式
2. 利用 Java 的动态代理和 Kotlin 的委托模式
首先需要实现一个通用的动态代理,新建一个 Kotlin 文件 DelegateObject.kt
,这里通过 inline
和 reified
关键字,获取到泛型的 class 信息
import java.lang.reflect.InvocationHandler
import java.lang.reflect.Proxy
inline fun <reified T> noOpDelegate() : T {
val javaClass = T::class.java
return Proxy.newProxyInstance(javaClass.classLoader, arrayOf(javaClass), no_op_invocationHandler) as T
}
val no_op_invocationHandler = InvocationHandler { _, _, _ -> }
这样就可以获取到任意一个接口的一个对象,只是没有具体的实现。接着再利用 Kotlin 的 by
关键字实现对象委托
val myActivityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
}
由于 Kotlin 委托模式的原理,实际上在编译期间也是会生成 ActivityLifecycleCallbacks
的所有方法,先来看看转译后的实现
private final Application.ActivityLifecycleCallbacks myActivityLifecycleCallbacks = (Application.ActivityLifecycleCallbacks)(new Application.ActivityLifecycleCallbacks() {
// $FF: synthetic field
private final Application.ActivityLifecycleCallbacks $$delegate_0;
{
int $i$f$noOpDelegate = false;
Class javaClass$iv = Application.ActivityLifecycleCallbacks.class;
Object var10001 = Proxy.newProxyInstance(javaClass$iv.getClassLoader(), new Class[]{javaClass$iv}, DelegateObjectKt.getNo_op_invocationHandler());
if (var10001 == null) {
throw new NullPointerException("null cannot be cast to non-null type android.app.Application.ActivityLifecycleCallbacks");
} else {
this.$$delegate_0 = (Application.ActivityLifecycleCallbacks)var10001;
}
}
public void onActivityCreated(@NonNull @NotNull Activity activity, @Nullable @org.jetbrains.annotations.Nullable Bundle savedInstanceState) {
Intrinsics.checkNotNullParameter(activity, "activity");
this.$$delegate_0.onActivityCreated(activity, savedInstanceState);
}
public void onActivityDestroyed(@NonNull @NotNull Activity activity) {
Intrinsics.checkNotNullParameter(activity, "activity");
this.$$delegate_0.onActivityDestroyed(activity);
}
public void onActivityPaused(@NonNull @NotNull Activity activity) {
Intrinsics.checkNotNullParameter(activity, "activity");
this.$$delegate_0.onActivityPaused(activity);
}
public void onActivityResumed(@NonNull @NotNull Activity activity) {
Intrinsics.checkNotNullParameter(activity, "activity");
this.$$delegate_0.onActivityResumed(activity);
}
public void onActivitySaveInstanceState(@NonNull @NotNull Activity activity, @NonNull @NotNull Bundle outState) {
Intrinsics.checkNotNullParameter(activity, "activity");
Intrinsics.checkNotNullParameter(outState, "outState");
this.$$delegate_0.onActivitySaveInstanceState(activity, outState);
}
public void onActivityStarted(@NonNull @NotNull Activity activity) {
Intrinsics.checkNotNullParameter(activity, "activity");
this.$$delegate_0.onActivityStarted(activity);
}
public void onActivityStopped(@NonNull @NotNull Activity activity) {
Intrinsics.checkNotNullParameter(activity, "activity");
this.$$delegate_0.onActivityStopped(activity);
}
});
现在已经将 ActivityLifecycleCallbacks 的匿名内部类对象委托给了 noOpDelegate
生成的代理对象。这样需要用到具体哪个方法时,只需要再次重写即可,例如文章最开始的例子可以变为
val myActivityLifecycleCallbacks = object : Application.ActivityLifecycleCallbacks by noOpDelegate() {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
TODO("Not yet implemented")
}
override fun onActivityDestroyed(activity: Activity) {
TODO("Not yet implemented")
}
}
经过精简的代码可以使代码更加简洁,可以更好的聚焦业务实现