在 kotlin 中将侦听器对象作为函数参数传递 [英] Passing a listener object as a function parameter in kotlin

查看:26
本文介绍了在 kotlin 中将侦听器对象作为函数参数传递的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to pass a listener from an action to a class (an adapter).

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

In java (code from the 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):

Now I'm trying to traslate to kotlin. I translate first the action (translation the action to kotlin):

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

此时仍然有效.适配器的代码仍然在 java 中,而类的代码在 kotlin 中.现在我将适配器转换为 kotlin:

At this point still works. With the code of the adapter still in java and code of the class in kotlin. Now I translate the adapter to kotlin:

fun setListener(listener: View.OnClickListener) {
    this.listener = listener 
}

现在不行了.该操作无法编译.

Now it doesn't work. The Action does not compile.

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

Error: cannot infer a type for this parameter "v". required View.OnClickListener. found (???) Unit.

我必须如何在这里做演员?为什么将参数从 kotlin 传递给 java 有效,而从 kotlin 传递给 kotlin 却无效?

How I must do the cast here? Why passing the parameter from kotlin to java works and from kotlin to kotlin it does not?

推荐答案

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

In the case of calling Java code you are benefitting from SAM conversion for single method interfaces written in Java. Then when you port the interface to Kotlin it does not allow this yet (Kotlin currently assumes you would use function references and lambdas instead of a single method interface).

问题与其他类似问题相同:Android - Kotlin - 对象必须声明为抽象或实现抽象成员

The problem is the same as from this other similar question: Android - Kotlin - object must be declared abstract or implement abstract member

由于这是 Kotin 接口,您不能使用 SAM 转换为 Lambda,这就是之前提供的其他答案不起作用的原因.如果这是一个 Java 接口,你可以这样做.您可以在 KT-7770 中跟踪 Kotlin 接口的 SAM 转换.

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.

如果你想让这段代码更符合 Kotlin 的习惯,你需要函数引用或 lambdas 而不是接口,你应该这样做而不是依赖 SAM 转换.您可以在 高阶函数和 Lambda 中阅读更多相关信息.这超出了您的问题范围,无法更详细地讨论.

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 在另一个答案中提到的,您必须传入一个实现此接口的类的实例.这称为对象表达式,如下所示:

Therefore as mentioned in another answer by @joakim, you must pass in a instance of a class that implements this interface. This is called an Object Expression and looks like:

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

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

Or realistically you should change your Kotlin port of the code to accept a reference to a function so that a lambda can be passed in directly. That would be more idiomatic and you would be able to call it as you were originally attempting.

这篇关于在 kotlin 中将侦听器对象作为函数参数传递的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆