【问题标题】:Kotlin customer interface declarationKotlin 客户界面声明
【发布时间】:2018-03-28 01:30:12
【问题描述】:

我在将现有的 Java 代码转换为 Kotlin 时遇到了一些问题,特别是在我与回收视图一起使用的自定义点击侦听器中。这是我到目前为止所得到的。

//this is the click listener interface (in Kotlin)
interface RecyclerClickListener {
  fun onClick(view: View, position: Int)
}

在 Java 中,这就是我创建和使用界面的方式

RecyclerClickListener clickListener = (view1, position) -> {
        setSelectedDate(dateCards.get(position).getDateTime());
        DateCardAdapter adapter = (DateCardAdapter) date_recycler_view.getAdapter();
        adapter.setSelected(position);
    };
    DateCardAdapter cardAdapter = new DateCardAdapter(dateCards, getActivity(), clickListener, true );

现在这就是我在 Kotlin 中尝试的方式(其中大部分是在 Android Studio 中自动转换的)

val listener: RecyclerClickListener = { view1: View, position: Int ->
        setSelectedDate(dateCards[position].dateTime)
        val adapter = sun_date_recycler_view.adapter as DateCardAdapter
        adapter.setSelected(position)
    } as RecyclerClickListener
    val cardAdapter = DateCardAdapter(dateCards, activity!!, listener, true)

但是当我启动我的应用程序时,我在尝试创建侦听器时不断收到 ClassException

Caused by: java.lang.ClassCastException: .fragments.SunFragment$onViewCreated$listener$1 cannot be cast to .interfaces.RecyclerClickListener

【问题讨论】:

    标签: android-recyclerview kotlin


    【解决方案1】:

    您声明的 lambda 是 (View, Int) -> Unit 类型,它不是 RecyclerClickListener 的子类型。 Kotlin 有一个名为 SAM conversion 的功能,允许您使用 lambda 创建函数式(单一方法)接口的匿名实例,但这仅适用于 Java 中定义的接口。

    (...) 请注意,此功能仅适用于 Java 互操作;由于 Kotlin 具有适当的函数类型,因此不需要将函数自动转换为 Kotlin 接口的实现,因此不受支持。

    1. 这是您的第一个(并且可能是目前最好的)解决方案 - 在 Java 中定义接口,您将能够毫无问题地在两种语言中使用 lambda。

    2. 另一种方法是使用 Kotlin 文档建议的函数类型,这将要求您使用类型 (View, Int) -> Unit 而不是定义新接口。这样,您在 Kotlin 和 Java 中的 lambda 都可以按原样工作(没有强制转换)。您可以使用 typealias 通过名称而不是 Kotlin 代码中的函数类型来引用它,但这在 Java 中是不可见的:

      typealias RecyclerClickListener = (String, Int) -> Unit
      

      您还必须在任何 Java lambda 的末尾显式返回 Unit.INSTANCE

      (view, position) -> {
          System.out.println("Clicked");
          return Unit.INSTANCE;
      }
      

    您可以找到关于 Kotlin 接口以及 here 未来可能支持的 SAM 转换的讨论。

    【讨论】:

      【解决方案2】:

      如果您使用 IntelliJ 将定义此类侦听器定义为匿名内部类的 Java 类转换为 Kotlin,它将生成以下正确代码:

      val listener = object : RecyclerClickListener {
          override fun onClick(view: View, position: Int) {
              // ...
          }
      }
      

      顺便说一句,Kotlin 文档中描述了语法:https://kotlinlang.org/docs/reference/nested-classes.html#anonymous-inner-classes

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多