在 kotlin 中将侦听器对象作为函数参数传递

Passing a listener object as a function parameter in kotlin

我正在尝试将侦听器从操作传递到 class(适配器)。

在 java 中(来自操作的代码):

  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 中,class 的代码在 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

的方法

更新:请参阅 Kotlin SAM 支持:https://kotlinlang.org/docs/java-interop.html#sam-conversions 了解最新信息。

在调用 Java 代码的情况下,您将从 SAM 转换中受益,因为它适用于用 Java 编写的单一方法接口。然后,当您将接口移植到 Kotlin 时,它还不允许这样做(Kotlin 目前假定您将使用函数引用和 lambda,而不是单一方法接口)。

问题与另一个类似问题相同:

Since this is a Kotin interface, you cannot use the SAM conversion to a Lambda so that is why the other answer previously provided does not work. If this was a Java interface, you could do that. You can track SAM conversions for Kotlin interfaces in KT-7770.

If you wanted this code to be more idiomatic Kotlin you would want function references or lambdas instead of interfaces, and you should just do that instead of relying on SAM conversion. You can read more about that in Higher-Order Functions and Lambdas. This is outside the scope of your question to go into more detail.

因此,正如@joakim 在另一个答案中提到的,您必须传入一个实现此接口的 class 实例。这称为 Object Expression,看起来像:

object : View.OnClickListener {
    override fun onClick(v: View) {...}
})

或者实际上,您应该更改代码的 Kotlin 端口以接受对函数的引用,以便可以直接传入 lambda。这会更加地道,您可以像最初尝试的那样调用它。