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

时间:2017-05-25 21:59:27

标签: kotlin kotlin-interop

我试图将侦听器从动作传递给类(适配器)。

在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呢?

2 个答案:

答案 0 :(得分:9)

在调用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,您可能需要函数引用或lambda而不是接口,您应该这样做而不是依赖于SAM转换。您可以在Higher-Order Functions and Lambdas中详细了解相关内容。这不在你的问题范围之内,需要更详细。

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

  try {
        int i = Integer.parseInt(jTextField1.getText());
        jTextField1.setText(String.format("%012d", i));
    } catch (Exception e) {
        jTextField1.setText(String.format("%012d", 0));
    }
}             

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

答案 1 :(得分:5)

更改

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

})

import org.openqa.selenium.chrome.ChromeDriver
import org.openqa.selenium.chrome.ChromeOptions
import org.openqa.selenium.remote.DesiredCapabilities

waiting {
        timeout = 2
    }

    environments {

        // run via “./gradlew chromeTest”
        // See: http://code.google.com/p/selenium/wiki/ChromeDriver
        chrome {
            driver = {
                ChromeOptions options = new ChromeOptions()
                DesiredCapabilities capabilities = DesiredCapabilities.chrome()

                String chromiumPath = "/usr/bin/chromium-browser"
                String macChromePath = "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"

                def chromiumBinary = new File(chromiumPath)
                def isAgent = chromiumBinary.exists()
                def macChromeBinary = new File(macChromePath)
                if (isAgent) {
                    options.setBinary(chromiumBinary) //Set binary using file to avoid NoClassDefFound error on mac
                } else if (macChromeBinary.exists()) {
                    options.setBinary(macChromeBinary)
                }

                options.addArguments("headless")
                capabilities.setCapability(ChromeOptions.CAPABILITY, options)
                new ChromeDriver(capabilities)
            }
        }
    }

并实现View.OnClickListener

的方法