[英]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.