Kotlin调用async报suspension functions can be called only within coroutine body问题咨询
错误原因
- 你参考的旧教程适配的是早期Kotlin协程版本,早期协程库提供顶层
async函数,新版协程库已移除该API,所有协程构造器(launch/async等)都必须通过CoroutineScope调用,这是报错的直接诱因 handleLoadWebView本身就是挂起函数,内部使用runBlocking属于严重的反模式:runBlocking会阻塞当前线程,在Android主线程调用大概率会触发ANR,完全违背协程非阻塞的设计理念- 你当前写的
async { getTokenAsync() }.await()属于冗余写法,等价于直接调用getTokenAsync(),没有任何并发收益
解决方案
最优方案(推荐)
直接删除多余的runBlocking和async逻辑,直接调用挂起函数即可:
private suspend fun handleLoadWebView() { //some code here..... val token = getTokenAsync() val jsonResp = JSONObject(token) loadWebView(exampleActivity, jsonResp.getString("access_token"), subdomain, content, options) }
需保留async并发的场景(比如后续要同时执行多个挂起任务)
使用coroutineScope替代runBlocking,它是挂起函数不会阻塞线程,且自带协程作用域:
private suspend fun handleLoadWebView() = coroutineScope { //some code here..... // 此处作用域内可正常调用async val resp = async { getTokenAsync() } val token = resp.await() val jsonResp = JSONObject(token) loadWebView(exampleActivity, jsonResp.getString("access_token"), subdomain, content, options) }
如果一定要保留原有runBlocking写法(极不推荐),手动指定作用域调用async即可解决报错:
runBlocking{ // 手动指定当前runBlocking的作用域调用async val resp = this.async { getTokenAsync() } token = resp.await() val jsonResp = JSONObject(token) loadWebView(exampleActivity, jsonResp.getString("access_token"), subdomain, content, options) }
内容的提问来源于stack exchange,提问作者Cristobal BL
相关产品推荐
相关产品推荐

