如何声明一个与lambda一起使用的接口?

时间:2018-05-22 14:59:03

标签: android lambda interface kotlin

我声明了这样一个简单的界面:

   interface OnSomethingReadyListener {
        fun onSomethingReady()
    }

当然是一个二传手:

private val onSomethingReadyListeners = ArrayList<OnSomethingReadyListener>()

fun addOnSomethingReadyListener(callback: OnSomethingReadyListener) {
    onSomethingReadyListeners.add(callback)
}

但后来我发现我不能使用lambda:

something.addOnShopDataReadyListener { progressbar.visibility = View.GONE }

IDE给了我一个错误:

Type mismatch.
Required: SomeClass.OnSomethingReadyListener
Found:    () -> Unit

假设我想坚持使用lambda而不是匿名类(object : OnSomethingReadyListener {...})。我该如何申报OnSomethingReadyListener

2 个答案:

答案 0 :(得分:2)

SAM(单一抽象方法)转换仅支持Java接口,而不支持Kotlin接口。

The documentation说明了这个推理:

  

另请注意,此功能仅适用于Java互操作;由于Kotlin具有适当的函数类型,因此不需要将函数自动转换为Kotlin接口的实现,因此不受支持。

KT-7770 requests this functionality,如果您想跟踪是否正在考虑它。

实现所需目标的推荐方法是将OnSomethingReadyListener替换为() -> Unit类型的参数,如下所示:

private val onSomethingReadyListeners = ArrayList<() -> Unit>()

fun addOnSomethingReadyListener(callback: () -> Unit) {
    onSomethingReadyListeners.add(callback)
}

然后,您可以使用类似

的内容调用这些侦听器
onSomethingReadyListeners.forEach { it.invoke() }

答案 1 :(得分:0)

您必须将此函数声明为:

fun addOnSomethingReadyListener(block: (OnSomethingReadyListener) -> Unit)

然后你可以按照以下方式调用它:

addOnSomethingReadyListener {
  // TODO
}