繁体   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