[英]Return value from suspend function when other flow is completed
我有两个挂起函数,它们是 callbackFlow。 我从返回 String 的 suspend function 调用其中之一。 我想在 serializeEvent() function 中等待来自 getLocation() 的位置,并在获取值返回字符串之后。
suspend fun getLocation(applicationContext: Context) = callbackFlow {
val locationProvider = LocationServices.getFusedLocationProviderClient(applicationContext)
if (isLocationPermissionGranted(applicationContext)) {
locationProvider.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, null)
.addOnSuccessListener {
if (it != null) {
trySend(it)
} else {
launch { trySend(getLastKnownLocation(locationProvider)) }
}
}
}
}
private suspend fun getLastKnownLocation(locationProvider: FusedLocationProviderClient) = callbackFlow {
runCatching {
locationProvider.lastLocation
.addOnSuccessListener { trySend(it) }
.addOnCanceledListener { trySend(null) }
.addOnFailureListener { trySend(null) }
}.onFailure {
trySend(null)
}
awaitClose { this.cancel() }
}
从getLastKnownLocation()
获取值时如何返回字符串
suspend fun serializeEvent(eventJson: JSONObject): String {
CoroutineScope(Dispatchers.Default).launch {
LocationProvider.getLocation(getApplicationContext!!).collect {
}
}
//some code here
return eventJson.toString()
}
使用callbackFlow
将 Google Task 变成 Flow 没有意义,因为 Task 只产生一个东西,而不是一系列的东西。 通常,将协程转换为仅返回一次的回调的方法是使用suspendCoroutine
或suspendCancellableCoroutine
。
但是,已经提供了Task.await()
扩展 suspend function ,因此您可以将其与协程同步使用。 (确保您使用的是位置库的-ktx
版本。)您不使用侦听器,而是用 try/catch 包围它。
如果没有可用位置,您似乎只想返回 null,所以我将重写 function:
suspend fun getLocationOrNull(applicationContext: Context): Location? {
if (!isLocationPermissionGranted(applicationContext)) {
return null
}
val locationProvider = LocationServices.getFusedLocationProviderClient(applicationContext)
return try {
locationProvider.getCurrentLocation(Priority.PRIORITY_HIGH_ACCURACY, null)
.await() ?: locationProvider.lastLocation.await()
} catch (e: Exception) {
Log.w(TAG, "Failed to retrieve current location")
null
}
}
在您的使用站点代码中,从暂停 function 中启动协程是没有意义的。如果您想做某事并在暂停 function 中等待它,您可以直接执行它而无需触发一些其他 CoroutineScope 中的新协程。
suspend fun serializeEvent(eventJson: JSONObject): String {
val knownLocation: Location? =
LocationProvider.getLocation(getApplicationContext!!)
//some code here. Do something with knownLocation, which might be null
return eventJson.toString()
}
旁注,在我看来你必须使用它的代码味道!!
获取您的应用程序上下文时。 Application Context 必须始终存在,因此它不需要是可为 null 的属性。
.addOnSuccessListener { trySend(it) }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.