如何在不阻塞调用函数的情况下从另一个挂起函数调用挂起函数?

How to call suspend function from another suspend function without blocking caller function?

我正在从一个挂起函数中调用一个 Api,在成功执行它之后,我需要调用另一个 Api(它也在另一个挂起函数中)。

    suspend fun updateSubscription(body: Map<String, Any>): NetworkResponse<SubscriptionUpdateResponse> =
        withContext(Dispatchers.IO) {
            val response = networkManager.execute(
                networkManager.updateSubscriptionApi(body)
            )
            val data = response.body()
            if (response.isSuccessful) {
                fetchSubscriptions() // suspend function which call another api, should run without blocking
            }
            return@withContext parseNetworkResponse(response, data)
        }

我想调用updateSubscriptionApi,在它成功执行后,无阻塞地调用fetchSubscription,结果是return updateSubscription

目前,fetchSubscription 也在阻止 updateSubscription。我试图像这样在 async 块中调用 updateSubscription 但没有成功。

async{ updateSubscription() }

如何在不阻塞 updateSubscription 的情况下调用 fetchSubscriptions()

不幸的是,当函数 returns 被认为是 Kotlin 中的反模式并且实现它时有一些困难。

但首先,简单的事情:

  1. 您确定需要 IO 调度程序吗?你说网络调用是挂起的,意思是非阻塞的,不需要专门的IO调度器。

  2. 如果你确实需要它(它实际上是一个阻塞调用),请不要将所有代码包装在其中,而只是那个调用。

现在,困难的部分。为了也能够启动协同程序,考虑在哪个范围内启动它至关重要。Kotlin 强烈建议使用结构化并发,这意味着在 UI 元素的定义明确的范围内启动所有内容( activity 等)。在您的情况下,您必须将范围作为参数显式传递给函数。通常你会将其声明为 CoroutineScope 上的扩展,但由于 coroutineContext 上的命名冲突,这不适用于暂停功能,它既是全局 val 又是 属性 共 CoroutineScope。这意味着您的代码可能如下所示:

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

suspend fun updateSubscription(
        scope: CoroutineScope,
        body: Map<String, Any>
): NetworkResponse<SubscriptionUpdateResponse> {
    val response = withContext(Dispatchers.IO) { // only if you need it!
        networkManager.execute(networkManager.updateSubscriptionApi(body))
    }
    if (response.isSuccessful) {
        scope.launch { fetchSubscriptions() }
    }
    return parseNetworkResponse(response, response.body())
}