我正在尝试使用rxjava链将交互器重写为kotlin流。在LocationHandlerImpl中,我正在使用LocationService获取我的当前位置。在addOnSuccessListener和addOnFailureListener中,我正在发出模型,但有错误:
“只能在协程体内调用悬浮功能”。我做错了吗?但我可以在听众之外调用“发出”(在流生成器下面查看)
答案 0 :(得分:2)
您似乎正在尝试从Android定位服务获取最后一个位置。这是Google Play服务中许多Task
回叫电话之一。 Kotlin已经有一个kotlinx-coroutines-play-services
模块,可以提供功能
suspend fun <T> Task<T>.await(): T?
在您的项目中,只需编写以下内容即可:
suspend fun getMyLocation(): Location? =
LocationServices.getFusedLocationProvider(context)
.lastLocation
.await()
如果要将其与其他基于Flow
的代码集成,请添加此包装器函数:
fun <T> Task<T>.asFlow() = flow { emit(await()) }
现在您可以写
fun getLocationAsFlow(): Flow<Location?> =
LocationServices.getFusedLocationProvider(context)
.lastLocation
.asFlow()
如果出于教育目的,您希望了解如何在没有附加模块的情况下直接实施该方法,那么最直接的方法如下:
suspend fun getLocationAsFlow() = flow {
val location = suspendCancellableCoroutine<Location?> { cont ->
LocationServices.getFusedLocationProvider(context)
.lastLocation
.addOnCompleteListener {
val e = exception
when {
e != null -> cont.resumeWithException(e)
isCanceled -> cont.cancel()
else -> cont.resume(result)
}
}
}
emit(location)
}
这是将Task.await()
的简化实现内联到其使用站点中的结果。
答案 1 :(得分:1)
如Prokash(here)所述,流被设计为自包含的。您的位置服务侦听器不在Flow的范围内。
但是,您可以签出callbackFlow
,它为您提供了使用基于回调的API构建流所需的机制。
Callback Flow Documentation,请注意,回调流程仍处于实验阶段。
答案 2 :(得分:0)
基于Coroutines的GitHub页面上的issue:
流量被设计为自包含,可重播的冷流,因此 超出其自身范围的发射将不属于 合同。
您需要使用Channel
之类的替代项来等待currently in development的ConflatedBroadcastChannel
。