You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin:如何在继续执行前等待协程完成?

解决Android协程等待异步任务完成后执行后续代码的问题

首先,你当前代码的核心问题是:deleteTable()和getData(companyName)在协程外部同步执行,此时协程还未完成companyName的获取,companyName仍为初始空字符串,无法满足getData的依赖需求。另外,你的finraGetCfruid作为挂起函数,用Volley回调的实现方式是错误的——Volley请求是异步的,函数会直接返回空的cfruid,根本没等请求完成。

第一步:修正协程执行顺序

把依赖companyName的操作放到协程内部,确保在获取到companyName之后再执行:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    viewModel.currentStock.observe(viewLifecycleOwner) { stock ->
        lifecycleScope.launch {
            // 切换到IO线程执行网络请求
            val companyName = withContext(Dispatchers.IO) {
                getCompanyName(stock)
            }
            // 拿到companyName后再执行后续操作
            deleteTable()
            getData(companyName)
        }
    }
}

这里直接将deleteTable和getData放入launch的协程体内,在withContext获取到companyName后执行,保证了执行顺序,无需额外调用join——协程内部默认是顺序执行的。

第二步:修复挂起函数的异步逻辑

你的finraGetCfruid是suspend函数,但Volley的回调方式没有真正挂起协程,函数会直接返回空值。需要用suspendCancellableCoroutine将Volley的回调转换成挂起函数,让协程等待请求完成:

private suspend fun finraGetCfruid(companyName: String): String = suspendCancellableCoroutine { cont ->
    val url = "https://www.finra.org/finra-data/fixed-income/corp-and-agency"
    val queue = Volley.newRequestQueue(requireActivity())

    val stringRequest = object : StringRequest(Request.Method.GET, url,
        { /* 无需处理响应体时留空即可 */ },
        { error ->
            Log.e("Error", error.toString())
            cont.resumeWithException(error) // 请求失败时抛出异常
        }) {
        override fun parseNetworkResponse(response: NetworkResponse): Response<String> {
            val cookies = HttpCookie.parse(response.headers?.get("Set-Cookie"))
            val indexOfEqualSign = cookies[0].toString().indexOf('=')
            val cfruid = cookies[0].toString().substring(indexOfEqualSign + 1)
            
            datainterface.getMoreData(companyName, cfruid)
            cont.resume(cfruid) // 请求成功时返回结果
            
            return super.parseNetworkResponse(response)
        }
    }

    queue.add(stringRequest)
    
    // 协程取消时同步取消Volley请求,避免内存泄漏
    cont.invokeOnCancellation {
        stringRequest.cancel()
    }
}

用suspendCancellableCoroutine可以将回调式异步操作转为挂起函数,Volley请求完成后通过cont.resume()返回结果,失败则用cont.resumeWithException()抛出异常,同时支持协程取消时同步终止Volley请求,避免资源浪费。

补充说明

  • 网络请求必须放在IO线程执行,因此用withContext(Dispatchers.IO)切换线程;lifecycleScope会自动绑定页面生命周期,避免协程内存泄漏。
  • 你之前尝试的job.join()报错,是因为join()是挂起函数,必须在协程内部调用,不能直接在UI线程的同步代码中使用——这也是不推荐runBlocking的原因,它会阻塞UI线程,影响页面流畅度。

内容的提问来源于stack exchange,提问作者David Frick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 17:12:48