首页 文章

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

提问于
浏览
4

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

在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 
}

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

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

我怎么必在这里演员?为什么将参数从kotlin传递到java工作,从kotlin传递到kotlin它不是?

2 回答

  • 5

    在调用Java代码的情况下,您可以从使用Java编写的单个方法接口进行SAM转换 . 然后,当您将接口移植到Kotlin时,它还不允许这样做(Kotlin目前假设您将使用函数引用和lambdas而不是单个方法接口) .

    问题与其他类似问题相同:Android - Kotlin - object must be declared abstract or implement abstract member

    由于这是一个Kotin界面,因此您无法将SAM转换用于Lambda,这就是为什么之前提供的其他答案不起作用的原因 . 如果这是一个Java接口,你可以这样做 . 您可以在KT-7770中跟踪Kotlin接口的SAM转换 . 如果你想让这个代码更加惯用Kotlin,你会想要函数引用或lambdas而不是接口,你应该这样做而不是依赖于SAM转换 . 您可以在高阶函数和Lambdas中阅读更多相关信息 . 更详细地说,这超出了您的问题的范围 .

    因此,如@joakim的另一个答案所述,您必须传入实现此接口的类的实例 . 这被称为Object Expression,看起来像:

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

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

  • 8

    更改

    adapterRecyclerView!!.setListener  { v  ->
                          SomeCodehere....
    }
    

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

    并实现View.OnClickListener的方法

相关问题