为什么我不能像 rxJava.Single.create 这样在 Kotlin Flow 中使用 emit 函数?
Why I can't use an emit function in Kotlin Flow like rxJava.Single.create?
我正在尝试将带有 rxjava 链的交互器重写为 kotlin 流。在 LocationHandlerImpl 中,我使用 LocationService 来获取我的当前位置。在 addOnSuccessListener 和 addOnFailureListener 中,我正在发出我的模型但有错误:
“挂起函数只能在协程体内调用”。我做错了吗?但是我可以在听众之外调用 emit(看下面的流生成器)
如 Prokash (here) 所述,流设计为自包含的。您的位置服务侦听器不在 Flow 的范围内。
不过,您可以查看 callbackFlow
,它为您提供了使用基于回调 API 构建流程所需的机制。
Callback Flow Documentation,请注意回调流程仍处于实验阶段。
您似乎正试图从 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()
如果出于教育目的,您希望了解如何在没有附加模块的情况下直接实现它,那么最直接的方法如下:
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()
的简化实现内联到其使用站点的结果。
我正在尝试将带有 rxjava 链的交互器重写为 kotlin 流。在 LocationHandlerImpl 中,我使用 LocationService 来获取我的当前位置。在 addOnSuccessListener 和 addOnFailureListener 中,我正在发出我的模型但有错误:
“挂起函数只能在协程体内调用”。我做错了吗?但是我可以在听众之外调用 emit(看下面的流生成器)
如 Prokash (here) 所述,流设计为自包含的。您的位置服务侦听器不在 Flow 的范围内。
不过,您可以查看 callbackFlow
,它为您提供了使用基于回调 API 构建流程所需的机制。
Callback Flow Documentation,请注意回调流程仍处于实验阶段。
您似乎正试图从 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()
如果出于教育目的,您希望了解如何在没有附加模块的情况下直接实现它,那么最直接的方法如下:
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()
的简化实现内联到其使用站点的结果。