簡體   English   中英

其他流程完成時suspend的返回值function

[英]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 只產生一個東西,而不是一系列的東西。 通常,將協程轉換為僅返回一次的回調的方法是使用suspendCoroutinesuspendCancellableCoroutine

但是,已經提供了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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM