I'm learning Kotlin and trying to use LiveData with it. Since LiveData library is written in Java, Kotlin should support SAM conversions.
LiveData
class has method observe
with two arguments, Observer
and LifecycleOwner
:
void observe (LifecycleOwner owner, Observer<T> observer)
Both are interfaces with single method. When I use SAM lambdas for both arguments it works fine:
val liveData = MutableLiveData<Int>()
liveData.observe({ lifecycleOwner.lifecycle }, { invokeMyMethod(it) })
Also it works when I provide object and SAM lambda with specific type (Observer
):
val liveData = MutableLiveData<Int>()
liveData.observe(lifecycleOwner, Observer { invokeMyMethod(it) })
However, when I'm trying to use object for one argument and SAM lambda without type for another argument:
val liveData = MutableLiveData<Int>()
liveData.observe(lifecycleOwner, { invokeMyMethod(it) })
it gives me compilation error. But why I can't write code like this? This is exactly what I want, compact and no boilerplate code. There is only one observe
method in LiveData
, why I have to specify the type for lambda?
Compiler produces such error:
Type mismatch. Required: Observer!>, Found: () → Unit
Small update, I've just checked this combination and it also doesn't work:
val liveData = MutableLiveData<Int>()
liveData.observe({ lifecycleOwner.lifecycle }, Observer { invokeMyMethod(it) })
So it works when both arguments are SAM lambdas, but doesn't work when one is SAM lambda and another is SAM lambda with specified type. In this case compiler also gives the same Type mismatch
error.
This is https://youtrack.jetbrains.com/issue/KT-14984. And according to that, it should finally be fixed in Kotlin 1.3, but the type inference changes required are opt-in for now and need to be enabled explicitly: https://discuss.kotlinlang.org/t/new-type-inference-in-kotlin-1-3-0-rc-190/9914/2
Your observation seems to be correct, but I won't be able to answer you why.
We see that Kotlin sees either LifecycleOwner, Observer
or () -> Lifecycle, (Int?) -> Unit
. As for why you don't see one with each combination, only people who work on Kotlin would know!
However, I'll be able to give you a workaround.
Add this extension function to your project:
inline fun <T> LiveData<T>.observe(lifecycleOwner: LifecycleOwner, crossinline observer: (T?) -> Unit) {
observe(lifecycleOwner, Observer { observer(it) })
}
And now it'll magically work (assuming your extension function is imported)!
fun blah() {
liveData.observe(lifecycleOwner) { // <-- trailing lambda
invokeMyMethod(it)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With