如何在不阻塞调用函数的情况下从另一个挂起函数调用挂起函数?
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 中的反模式并且实现它时有一些困难。
但首先,简单的事情:
您确定需要 IO
调度程序吗?你说网络调用是挂起的,意思是非阻塞的,不需要专门的IO调度器。
如果你确实需要它(它实际上是一个阻塞调用),请不要将所有代码包装在其中,而只是那个调用。
现在,困难的部分。为了也能够启动协同程序,考虑在哪个范围内启动它至关重要。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())
}
我正在从一个挂起函数中调用一个 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 中的反模式并且实现它时有一些困难。
但首先,简单的事情:
您确定需要
IO
调度程序吗?你说网络调用是挂起的,意思是非阻塞的,不需要专门的IO调度器。如果你确实需要它(它实际上是一个阻塞调用),请不要将所有代码包装在其中,而只是那个调用。
现在,困难的部分。为了也能够启动协同程序,考虑在哪个范围内启动它至关重要。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())
}