当前位置: 首页 > news >正文

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,这里通过 inlinereified 关键字,获取到泛型的 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")
        }
    }

经过精简的代码可以使代码更加简洁,可以更好的聚焦业务实现

相关文章:

  • 如何通过MDM高效管理企业的Android平板?
  • [每日动态]科技新闻每日信息差2025年2月14日
  • 景联文科技:以精准标注赋能AI未来,打造高质量数据基石
  • 数据结构--八大排序算法
  • 2025年单片机毕业设计选题物联网计算机电气电子通信类
  • 开发美颜相机录制视频时,对于音频数据的处理
  • ECharts鼠标悬浮提示框数字设置鼠标在左侧时 tooltip 显示到右侧,鼠标在右侧时 tooltip 显示到左侧。
  • OpenCV机器学习(3)期望最大化(Expectation-Maximization, EM)算法cv::ml::EM
  • 深入解析 vLLM:高性能 LLM 服务框架的架构之美(上)
  • 深入探讨复变函数:核心概念与关键应用
  • Day1 25/2/14 FRI
  • 树莓集团海南自贸港布局,探索数字经济无限可能
  • 牛客小白月赛110 —— D 智乃与长短期主义者博弈 python 补题 + 题解
  • 文件操作/标准IO(20250214)
  • 文件系统惹(细)
  • springboot mybatis-plus 集成多数据源
  • GF1 遥感影像镶嵌拼接
  • C++ 多态
  • 2.5 使用注解进行单元测试详解
  • 【vue3】实现pdf在线预览的几种方式
  • 专注江苏网站建设/网络推广哪个平台最好
  • 关于我们做网站/广州网站关键词推广
  • 网站后台的关键词/杭州优化外包哪里好
  • 榆林做网站的公司电话/软件网站排行榜
  • 网页网站怎么做/深圳网站建设找哪家公司好
  • 福州做网站的公司多少钱/互联网舆情监测系统