Kotlin SAM转换不适用于带有两个参数的函数

时间:2018-12-01 21:10:26

标签: android kotlin android-livedata

我正在学习Kotlin,并尝试将LiveData与它一起使用。由于LiveData库是用Java编写的,因此Kotlin应该支持SAM转换。

LiveData类具有带有两个参数observeObserver的方法LifecycleOwner

void observe (LifecycleOwner owner, Observer<T> observer)

都是使用单一方法的接口。当我对两个参数都使用SAM lambda时,它可以正常工作:

val liveData = MutableLiveData<Int>()
liveData.observe({ lifecycleOwner.lifecycle }, { invokeMyMethod(it) })

当我提供特定类型(Observer)的对象和SAM lambda时,它也起作用:

val liveData = MutableLiveData<Int>()
liveData.observe(lifecycleOwner, Observer { invokeMyMethod(it) })

但是,当我尝试将object用于一个参数而将SAM lambda没有类型用于另一参数时:

val liveData = MutableLiveData<Int>()
liveData.observe(lifecycleOwner, { invokeMyMethod(it) })

它给了我编译错误。但是为什么我不能写这样的代码?这正是我想要的,紧凑,没有样板代码。 observe中只有一个LiveData方法,为什么我必须指定lambda的类型?

编译器会产生这样的错误:

  

类型不匹配。必需:观察员!>,找到:()→单位

小的更新,我刚刚检查了此组合,但它也无效:

val liveData = MutableLiveData<Int>()
liveData.observe({ lifecycleOwner.lifecycle }, Observer { invokeMyMethod(it) })

因此,当两个参数都是SAM Lambda时,它就起作用,但是当一个参数是SAM Lambda而另一个是具有指定类型的SAM Lambda时,则不起作用。在这种情况下,编译器也会给出相同的Type mismatch错误。

3 个答案:

答案 0 :(得分:2)

这是https://youtrack.jetbrains.com/issue/KT-14984。并且据此,它最终应该在Kotlin 1.3中修复,但是所需的类型推断更改目前已加入,并且需要显式启用:https://discuss.kotlinlang.org/t/new-type-inference-in-kotlin-1-3-0-rc-190/9914/2

答案 1 :(得分:1)

您的观察似乎是正确的,但我无法回答您的原因。

options

我们看到Kotlin看到LifecycleOwner, Observer() -> Lifecycle, (Int?) -> Unit。至于为什么您看不到带有每种组合的人,只有从事Kotlin的人才知道!


但是,我可以为您提供解决方法。

将此扩展功能添加到您的项目中:

inline fun <T> LiveData<T>.observe(lifecycleOwner: LifecycleOwner, crossinline observer: (T?) -> Unit) {
    observe(lifecycleOwner, Observer { observer(it) })
}

现在它将神奇地工作(假设您的扩展功能已导入)!

fun blah() {
    liveData.observe(lifecycleOwner) { // <-- trailing lambda
        invokeMyMethod(it)
    }
}

答案 2 :(得分:0)

好消息是 kotlin 现在可以正确处理具有多个参数的函数的 SAM 转换。

observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)

只需更新到最新的实时数据版本,他们也deprecated当前观察

示例:

livedata.observe(viewLifecycleOwner, ::bindData)

private fun bindData(unit: Unit) { }