如何在Kotlin协程中等待请求完成并返回结果?
正确实现协程等待API请求并返回结果的方案
错误实现分析
你之前的两种写法问题出在:
- 第一种实现:普通函数里启动协程后直接返回初始值,协程在后台异步执行,函数返回时API请求还没完成,所以拿到的永远是默认的"unknown",后续协程修改变量的操作对已返回的结果没有影响。
- 第二种实现:
job变量定义在runBlocking内部,外部根本无法访问;同时用Dispatchers.Main执行API请求(网络请求必须放在IO线程),再加上主线程被runBlocking阻塞后,协程需要主线程资源却无法获取,直接导致死锁停滞。
推荐实现方案
方案1:使用挂起函数(规范做法,适配协程上下文)
把函数改成suspend类型,让它在协程环境中被调用,完全避免线程阻塞:
suspend fun getClient(): String? { // 强制在IO线程执行API请求(如果你的callsApi.getClient本身是挂起函数且已处理线程切换,可省略withContext) val response = withContext(Dispatchers.IO) { callsApi.getClient(GetClientDTO(phonenumberString)) } val body = response.body() // 省略body解析为nameObject的逻辑... return body?.let { nameObject.getString("fullName") } ?: "unknown" }
调用示例(必须在协程作用域内,比如ViewModel的viewModelScope或Activity的lifecycleScope):
// 在ViewModel中调用 viewModelScope.launch { val nameClient = getClient() // 拿到结果后处理UI或业务逻辑 }
方案2:同步阻塞获取结果(仅适用于非UI线程场景,不推荐)
如果必须在非协程环境同步拿到结果,用runBlocking指定IO线程,避免阻塞主线程:
fun getClientBlocking(): String? { return runBlocking(Dispatchers.IO) { val response = callsApi.getClient(GetClientDTO(phonenumberString)) val body = response.body() // 省略解析逻辑... body?.let { nameObject.getString("fullName") } ?: "unknown" } }
注意:此方法会阻塞调用线程,绝对不能在主线程使用,否则会造成UI卡顿甚至ANR。
内容的提问来源于stack exchange,提问作者herz88888888
相关产品推荐
相关产品推荐

