将侦听器对象作为函数参数传递给kotlin
我试图从一个行动的一个监听器传递给一个类(一个适配器)。
在java中(来自Action的代码):
private void setListeners() { adapterRecyclerView.setListener( new View.OnClickListener() { @Override public void onClick(View v) { SomeCodehere.... } }); }
(来自适配器的代码)
public void setListener(View.OnClickListener listener) { this.listener = listener; }
有用。
现在我正在试着去kotlin。 我首先翻译行动(翻译行动kotlin):
private fun setListeners() { // !! is not fine i know adapterRecyclerView!!.setListener { v -> SomeCodehere.... } }
此时仍然有效。 使用适配器的代码仍然在java和kotlin类中的代码。 现在我把适配器翻译成kotlin:
fun setListener(listener: View.OnClickListener) { this.listener = listener }
现在它不工作。 该行动不编译。
错误:无法推断此参数“v”的类型。 需要View.OnClickListener。 找到(???)单位。
我该怎么做这里的演员? 为什么从kotlin到java的参数传递参数,从kotlin到kotlin呢?
更改
adapterRecyclerView!!.setListener { v -> SomeCodehere.... }
至
adapterRecyclerView!!.setListener(object : View.OnClickListener { })
并实现View.OnClickListener的方法
在调用Java代码的情况下,您可以从使用Java编写的单一方法接口的SAM转换中受益。 然后,当您将接口移植到Kotlin时,它不允许这样做(Kotlin现在假设您将使用函数引用和lambdas而不是单个方法接口)。
问题是从这个其他类似的问题相同: Android – Kotlin – 对象必须声明为抽象或实现抽象成员
由于这是一个Kotin接口,因此您不能使用SAM转换为Lambda,因此之前提供的其他答案不起作用。 如果这是一个Java界面,你可以做到这一点。 您可以在KT-7770中跟踪Kotlin接口的SAM转换。
如果你想让这个代码更加地道的Kotlin,你会想要函数引用或lambdas而不是接口,你应该这样做,而不是依靠SAM转换。 你可以在高阶函数和Lambdas中阅读更多。 这是超出你的问题的范围进入更多的细节。
因此,正如@joakim的另一个答案所述,您必须传入一个实现此接口的类的实例。 这称为对象表达式 ,如下所示:
object : View.OnClickListener { override fun onClick(v: View) {...} })
或者实际上你应该改变你的代码的Kotlin端口来接受一个函数的引用,这样lambda可以被直接传入。 这会更习惯,你可以像你最初尝试的那样调用它。