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

Kun*_*nte 5 kotlin kotlin-interop

我正在尝试将一个侦听器从一个动作传递给一个类(一个适配器).

在java中(来自Action的代码):

  private void setListeners() {
    adapterRecyclerView.setListener(
            new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    SomeCodehere....
                }
            });
}
Run Code Online (Sandbox Code Playgroud)

(来自适配器的代码)

public void setListener(View.OnClickListener listener) {
    this.listener = listener;
}
Run Code Online (Sandbox Code Playgroud)

有用.

现在我正试图转向kotlin.我首先翻译动作(将动作翻译为kotlin):

    private fun setListeners() {
    // !! is not fine i know
    adapterRecyclerView!!.setListener  { v  ->
                          SomeCodehere....
    }
}
Run Code Online (Sandbox Code Playgroud)

此时仍然有效.适配器的代码仍然在java和kotlin中的类的代码.现在我将适配器翻译为kotlin:

fun setListener(listener: View.OnClickListener) {
    this.listener = listener 
}
Run Code Online (Sandbox Code Playgroud)

现在它不起作用.Action没有编译.

错误:无法推断此参数"v"的类型.必需的View.OnClickListener.发现(???)单位.

我该怎么做演员?为什么将参数从kotlin传递给java工作,从kotlin传递给kotlin它不是?

Jay*_*ard 11

在调用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) {...}
})
Run Code Online (Sandbox Code Playgroud)

或者实际上你应该更改代码的Kotlin端口以接受对函数的引用,以便可以直接传入lambda.这将是更惯用的,你可以像原来的尝试一样调用它.


Joa*_*kim 6

更改

adapterRecyclerView!!.setListener  { v  ->
                      SomeCodehere....
}
Run Code Online (Sandbox Code Playgroud)

adapterRecyclerView!!.setListener(object : View.OnClickListener {

})
Run Code Online (Sandbox Code Playgroud)

并实现View.OnClickListener的方法

  • 只是一个友好的建议:!! 应该避免操作员.否则你将无法利用kotlin的null安全功能.您可以通过事先检查adapterRecyclerView的可为空性来对非null对象进行不明确的强制转换. (3认同)