我在将现有的 Java 代码转换为 Kotlin 时遇到了一些问题,特别是在我与回收 View 一起使用的自定义点击监听器中。这是我到目前为止所得到的。
//this is the click listener interface (in Kotlin)
interface RecyclerClickListener {
fun onClick(view: View, position: Int)
}
在 Java 中,这就是我创建和使用接口(interface)的方式
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
最佳答案
您声明的 lambda 类型为 (View, Int) -> Unit
,它不是 RecyclerClickListener
的子类型. Kotlin 有一个名为 SAM conversion 的功能。这允许您使用 lambdas 创建功能(单一方法)接口(interface)的匿名实例,但这仅适用于 Java 中定义的接口(interface)。
(...) note that this feature works only for Java interop; since Kotlin has proper function types, automatic conversion of functions into implementations of Kotlin interfaces is unnecessary and therefore unsupported.
(View, Int) -> Unit
而不是定义一个新的接口(interface)。这样,您在 Kotlin 和 Java 中的 lambda 都可以按原样工作(没有强制转换)。您可以使用 typealias
在 Kotlin 代码中通过名称而不是函数类型来引用它,但这在 Java 中是不可见的:typealias RecyclerClickListener = (String, Int) -> Unit
您还必须明确返回
Unit.INSTANCE
在任何 Java lambda 的末尾:(view, position) -> {
System.out.println("Clicked");
return Unit.INSTANCE;
}
您可以找到关于 Kotlin 接口(interface) future 可能支持的 SAM 转换的讨论 here .
关于android-recyclerview - Kotlin 客户界面声明,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49518823/