我正在学习Kotlin,并尝试将LiveData与它一起使用。由于LiveData库是用Java编写的,因此Kotlin应该支持SAM转换。
LiveData
类具有带有两个参数observe
和Observer
的方法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
错误。
答案 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)
您的观察似乎是正确的,但我无法回答您的原因。
我们看到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) { }