Kotlin中如何等待async协程任务完成后再执行后续逻辑
问题根源
你遇到的问题本质是异步逻辑和同步返回的矛盾:checkIfIDExistsInDatabase 是同步返回布尔值的函数,但内部的数据库查询逻辑是通过GlobalScope.launch异步执行的,函数返回的时候协程还没有完成查询操作,所以返回的永远是初始赋值的false。等协程查询到ID确实存在、修改isIDExists值、弹出提示的时候,findId里的判断逻辑早就执行完进入了插入分支,自然会出现插入和弹窗同时触发的问题。runBlocking 能解决问题是因为它会阻塞当前线程等待协程执行完成再返回结果,但如果在主线程调用会直接导致界面无响应,属于不符合安卓开发规范的用法。
优化方案
安卓场景下使用协程首先要弃用GlobalScope,改用和组件生命周期绑定的lifecycleScope(Activity/Fragment中使用)或viewModelScope(ViewModel中使用),避免内存泄漏和无效任务执行。
核心思路是把异步查询逻辑改成挂起函数,通过协程的结构化并发串联整个判断流程,不需要阻塞线程也能拿到正确的查询结果。
优化后代码示例
1. 改造ID存在检查函数
// 改为挂起函数,直接返回数据库查询结果,不处理UI逻辑 private suspend fun checkIfIDExistsInDatabase(id: String): Boolean { // 自动切IO线程执行数据库查询,执行完成后返回结果 return withContext(Dispatchers.IO) { bbdViewModel.isIDExists(id) } }
2. 改造findId逻辑
private fun findId(targetId: String) { // 使用lifecycleScope启动协程,和页面生命周期绑定,页面销毁自动取消任务 lifecycleScope.launch { val idIsExists = checkIfIDExistsInDatabase(targetId) if (idIsExists) { // lifecycleScope默认运行在主线程,不需要手动用Handler切线程,直接弹框 Dialog.getInstance(activity) .setMessage(R.string.id_already_exists_in_db) .setPositiveButton(R.string.ok, null) .show() } else { // 插入逻辑同样切IO线程执行,不会阻塞主线程 withContext(Dispatchers.IO) { // 执行你的ID插入数据库逻辑 insertIdToDB(targetId) } // 插入完成后的UI提示可以直接写在这里,自动回到主线程执行 } } }
方案优势
- 完全不需要阻塞线程,所有异步操作通过协程的挂起能力实现顺序执行,逻辑和同步代码一样清晰
- 生命周期绑定的协程Scope不会出现内存泄漏,页面销毁时未完成的任务会自动取消,避免空指针异常
- 不需要手动处理线程切换,协程会自动完成线程调度,代码更简洁易维护
内容的提问来源于stack exchange,提问作者Manish
相关产品推荐
相关产品推荐

