循环中逐个执行PDF生成任务:解决仅生成最后一个PDF的问题
解决循环中异步生成PDF仅最后一个生效的问题
你猜的没错!问题核心就是循环的同步执行速度远快于后台PDF生成的异步任务,而且你的全局变量(receiveUser、products这些)会被后续迭代覆盖,导致最后只有最后一次的PDF任务能拿到正确数据。要解决这个问题,我们需要让循环“等待”每次PDF生成完成后再走下一轮,用Kotlin协程来实现会非常顺畅。
第一步:把PDF生成改成可等待的挂起函数
首先,我们需要把异步的htmlToPDF包装成挂起函数,让协程能暂停等待它完成:
// 包装htmlToPDF为挂起函数,确保任务完成后才继续执行 suspend fun generatePdf(htmlContent: String) = suspendCoroutine<Unit> { continuation -> doAsync { htmlToPDF(htmlContent) // 执行你的PDF生成逻辑 continuation.resume(Unit) // 任务完成,通知协程继续 } }
第二步:用协程顺序执行每个PDF生成任务
接下来,我们用协程作用域(比如Activity的lifecycleScope,或者ViewModel的viewModelScope)来遍历数组,确保每个任务完成后再进入下一轮迭代:
// 在你的Activity或ViewModel中启动协程 lifecycleScope.launch { progressBar.setVisible() // 安全遍历invoice数组,避免空指针 multipleInvoice?.forEach { currentInvoice -> // 把变量改成局部的!避免被后续迭代覆盖 val receiveUser = MainActivity.users.find { it.codeZ == currentInvoice.customerCodeZ } val products = currentInvoice.retrieveInvoice(this@YourActivity) // 替换成你的Activity上下文 val receiveInvoice = currentInvoice // 生成当前invoice对应的HTML内容 val htmlContent = renderHTML() // 等待当前PDF生成完成,再进行下一个 generatePdf(htmlContent) } progressBar.setGone() }
为什么这样能解决问题?
- 局部变量避免覆盖:把
receiveUser、products改成forEach块内的局部变量,每个迭代的数据都是独立的,不会被后面的迭代修改。 - 协程暂停等待:
generatePdf是挂起函数,协程会在这里暂停,直到PDF生成任务完成,才会进入下一次forEach迭代,彻底解决了“循环跑太快”的问题。
额外提醒
如果你的renderHTML()方法依赖全局变量,最好也改成接收参数的形式,比如把receiveUser、products作为参数传进去,进一步避免全局状态带来的问题:
fun renderHTML(user: User?, products: List<Product>): String { // 用传入的参数生成HTML,而不是全局变量 }
内容的提问来源于stack exchange,提问作者user9172697
相关产品推荐
相关产品推荐

