如何从协程范围返回值

bla*_*awk 10 android kotlin kotlin-coroutines

有没有办法从协程范围返回值?例如像这样:

suspend fun signUpUser(signUpData : SignUpUserRequest) : User {

CoroutineScope(Dispatchers.IO).launch() {

        val response = retrofitInstance.socialSignUP(signUpData)
        if (response.success) {
            obj = response.data
        } else {
                obj = response.message
        }
    }.invokeOnCompletion {
        obj = response.message
    }

    return obj
}
Run Code Online (Sandbox Code Playgroud)

问题是一旦调用 signupUser 函数,立即返回 obj suspend 语句运行,而不是响应值..它不是按顺序运行的,我期望的是第一个响应来然后函数返回 obj 但它没有发生。为什么?

我试过运行阻塞,它达到了目的,但是有没有更好的方法可以在不阻塞的情况下完成相同的任务?或者可以吗?

提前致谢!

Ser*_*gey 6

您可以使用withContext函数在后台线程中运行代码并返回一些结果:

suspend fun signUpUser(signUpData : SignUpUserRequest): User = withContext(Dispatchers.IO) {    
    val response = retrofitInstance.socialSignUP(signUpData)
    if (response.success) response.data else response.message
}
Run Code Online (Sandbox Code Playgroud)

  • @blackHawk,您可以 `CoroutineScope(Dispatchers.IO).async { /* return last line */ }.await()` 但这并没有对此进行优化,并且每次调用函数时创建 `CoroutineScope` 都是一个坏主意。 (2认同)

Mir*_*ski 5

如果您需要并行运行作品,那么您可以使用coroutineScopeasync协程构建器函数。但是,在您的情况下,您只有一个请求,因此它可能是sequantial。正如前面的答案中提到的,您可以使用withContext. 这是文档的小说明:

使用给定的协程上下文调用指定的挂起块,挂起直到它完成,然后返回结果。

suspend fun getUser(signUpData: SignUpUserRequest): User = withContext(Dispatchers.IO) {
    // do your network request logic here and return the result
}
Run Code Online (Sandbox Code Playgroud)

请注意,当您使用带有函数的表达式主体时,请始终尝试显式注释返回类型。

编辑

协程使用常规 Kotlin 语法来处理异常:try/catch或内置辅助函数,如runCatching(内部使用try/catch)。当心总是会抛出未捕获的异常。但是,不同的协程构建器以不同的方式处理异常。阅读官方文档或其他来源(如this)总是好的。