如何将 Java 方法参考代码转换为 Kotlin
How to convert Java method reference code to Kotlin
我在 Java 中得到了这个代码:
mViewModel.getSetupData().observe(this, this::updateTime);
updateTime 方法接受一个参数。
将此代码转换为 Kotlin 时,以下内容不起作用:
mViewModel?.getSetupData()?.observe(this, ::updateTime)
IDE(android 工作室)抱怨
Type mismatch. Required: Observer. Found KFunction1.
有什么线索吗?
看来你可以提供
.observe(this, Observer { someClass ->
/*Here you can call your method*/
})
是的,它比 java 方法稍微冗长一点,但出于某种原因,Kotlin 无法推断 lambda 的类型。
对于面临相同问题的任何人,这需要是来自 Android LiveData api 的 Kotlin val
。它不能是一个函数。这是 updateTime
的正确代码,它代替函数工作:
private val updateTime = Observer<TimeMeasurement> {
setupTimeMeasurement ->
// Update the UI, in this case, a TextView.
updateTimerData(setupTimeMeasurement, mViewModel!!.currentTimeValue)
}
然后你可以这样称呼它:
mViewModel?.getCountdownData()?.observe(this, updateTime)
出于某种原因,Kotlin 在提供 observe
重载方面不够聪明:
// Java declaration
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
现在在Kotlin中我们可以通过两种方式调用这个方法:
// Default Kotlin conversion [ #1 ]
fun observe(owner : LifecycleOwner, observer : Observer<in T>)
// SAM conversions [ #2 ]
fun observe(owner: () -> Lifecycle, observer : (T) -> Unit)
我们缺少的是介于两者之间的东西,我们只为观察者参数提供函数。
如果您已经依赖 Android KTX 模块,即 androidx.fragment:fragment-ktx
(或至少 androidx.lifecycle:lifecycle-livedata-core-ktx
)下面的扩展应该已经可以访问了。否则你可以快速添加它:
// custom extension with function observer argument [ #3 ]
@MainThread inline fun <T> LiveData<T>.observe(
owner: LifecycleOwner,
crossinline onChanged: (T) -> Unit
): Observer<T> {
val wrappedObserver = Observer<T> { t -> onChanged.invoke(t) }
observe(owner, wrappedObserver)
return wrappedObserver
}
下面是调用的区别:
// reusable observer object
val myObserver = Observer<TimeMeasurement> { updateTime(it) }
// function that updates time
fun updateTime(time : TimeMeasurement){
// update views with time
}
override fun onCreate(savedInstanceState: Bundle?) {
/* ... */
// default call [ #1 ]
mViewModel.liveData.observe(this, myObserver)
// default call but with object expression for observer [ #1 ]
mViewModel.liveData.observe(this, Observer { updateTime(it) })
// alternatively [ #1 ]
mViewModel.liveData.observe(this, Observer(::updateTime))
// SAM conversions, lets us pass function reference or a lambda [ #2 ]
// in this case first argument is a lambda as well and it returns lifecycle
mViewModel.liveData.observe({ lifecycle }, ::updateTime)
// extension function call where we pass function reference as second argument [ #3 ]
mViewModel.liveData.observe(this, ::updateTime)
// or using lambda [ #3 ]
mViewModel.liveData.observe(this) { updateTime(it) }
}
我在 Java 中得到了这个代码:
mViewModel.getSetupData().observe(this, this::updateTime);
updateTime 方法接受一个参数。 将此代码转换为 Kotlin 时,以下内容不起作用:
mViewModel?.getSetupData()?.observe(this, ::updateTime)
IDE(android 工作室)抱怨
Type mismatch. Required: Observer. Found KFunction1.
有什么线索吗?
看来你可以提供
.observe(this, Observer { someClass ->
/*Here you can call your method*/
})
是的,它比 java 方法稍微冗长一点,但出于某种原因,Kotlin 无法推断 lambda 的类型。
对于面临相同问题的任何人,这需要是来自 Android LiveData api 的 Kotlin val
。它不能是一个函数。这是 updateTime
的正确代码,它代替函数工作:
private val updateTime = Observer<TimeMeasurement> {
setupTimeMeasurement ->
// Update the UI, in this case, a TextView.
updateTimerData(setupTimeMeasurement, mViewModel!!.currentTimeValue)
}
然后你可以这样称呼它:
mViewModel?.getCountdownData()?.observe(this, updateTime)
出于某种原因,Kotlin 在提供 observe
重载方面不够聪明:
// Java declaration
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)
现在在Kotlin中我们可以通过两种方式调用这个方法:
// Default Kotlin conversion [ #1 ]
fun observe(owner : LifecycleOwner, observer : Observer<in T>)
// SAM conversions [ #2 ]
fun observe(owner: () -> Lifecycle, observer : (T) -> Unit)
我们缺少的是介于两者之间的东西,我们只为观察者参数提供函数。
如果您已经依赖 Android KTX 模块,即 androidx.fragment:fragment-ktx
(或至少 androidx.lifecycle:lifecycle-livedata-core-ktx
)下面的扩展应该已经可以访问了。否则你可以快速添加它:
// custom extension with function observer argument [ #3 ]
@MainThread inline fun <T> LiveData<T>.observe(
owner: LifecycleOwner,
crossinline onChanged: (T) -> Unit
): Observer<T> {
val wrappedObserver = Observer<T> { t -> onChanged.invoke(t) }
observe(owner, wrappedObserver)
return wrappedObserver
}
下面是调用的区别:
// reusable observer object
val myObserver = Observer<TimeMeasurement> { updateTime(it) }
// function that updates time
fun updateTime(time : TimeMeasurement){
// update views with time
}
override fun onCreate(savedInstanceState: Bundle?) {
/* ... */
// default call [ #1 ]
mViewModel.liveData.observe(this, myObserver)
// default call but with object expression for observer [ #1 ]
mViewModel.liveData.observe(this, Observer { updateTime(it) })
// alternatively [ #1 ]
mViewModel.liveData.observe(this, Observer(::updateTime))
// SAM conversions, lets us pass function reference or a lambda [ #2 ]
// in this case first argument is a lambda as well and it returns lifecycle
mViewModel.liveData.observe({ lifecycle }, ::updateTime)
// extension function call where we pass function reference as second argument [ #3 ]
mViewModel.liveData.observe(this, ::updateTime)
// or using lambda [ #3 ]
mViewModel.liveData.observe(this) { updateTime(it) }
}