【问题标题】:How kotlin makes setOnClickListener accept functions as parameterkotlin 如何让 setOnClickListener 接受函数作为参数
【发布时间】:2016-12-16 08:45:38
【问题描述】:

在 kotlin 中,我们可以像这样使用setOnClickListener()

view.setOnClickListener { println("Hello") }

但如果我定义自己的接口,我只能像这样传递匿名对象:

obj.setMyListener(object: MyListener() {
    ...
})

我只是想知道他们如何让setOnClickListener() 接受一个函数而不是一个匿名对象。

【问题讨论】:

  • MyListener 只需要一种方法。否则你需要创建一个object:MyListener

标签: android kotlin


【解决方案1】:

根据关于Java interop 的Kotlin 文档,对于用Java 定义的功能接口,您可以使用SAM 转换。

就像 Java 8 一样,Kotlin 支持 SAM 转换。这意味着 Kotlin 函数字面量可以自动转换为 具有单个非默认方法的 Java 接口的实现, 只要接口方法的参数类型匹配 Kotlin 函数的参数类型。

val runnable = Runnable { println("This runs in a runnable") }

val executor = ThreadPoolExecutor()
// Java signature: void execute(Runnable command)
executor.execute { println("This runs in a thread pool") }

但是,Kotlin 具有函数类型,因此 SAM 转换不适用于 Kotlin 中定义的接口:

还请注意,此功能仅适用于 Java 互操作;自从科特林 具有适当的函数类型,自动将函数转换为 Kotlin 接口的实现是不必要的,因此 不支持。


可能的解决方案:

  1. 用 Java 定义接口。如果它是可以从 Java 代码中使用的库/代码,则很有用。
  2. 使方法接收一个函数作为参数:

    // Example listener receives a bool and return unit.  
    fun setMyListener(listener: (isChecked: Bool) -> Unit) { ... }  
    // Usage:  
    obj.setMyListener { isChecked -> }
    
  3. 使用类型别名(仅在 Kotlin 1.1+ 中支持):

    typealias MyListener = (Bool) -> Unit
    fun setMyListener(listener: MyListener) { ... }
    

【讨论】:

    猜你喜欢
    • 2012-10-22
    • 1970-01-01
    • 2020-06-28
    • 2021-10-29
    • 1970-01-01
    • 2020-05-15
    • 2020-07-20
    • 2022-12-13
    相关资源
    最近更新 更多