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

循环中逐个执行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()
}

为什么这样能解决问题?

  1. 局部变量避免覆盖:把receiveUser、products改成forEach块内的局部变量,每个迭代的数据都是独立的,不会被后面的迭代修改。
  2. 协程暂停等待:generatePdf是挂起函数,协程会在这里暂停,直到PDF生成任务完成,才会进入下一次forEach迭代,彻底解决了“循环跑太快”的问题。

额外提醒

如果你的renderHTML()方法依赖全局变量,最好也改成接收参数的形式,比如把receiveUser、products作为参数传进去,进一步避免全局状态带来的问题:

fun renderHTML(user: User?, products: List<Product>): String {
    // 用传入的参数生成HTML,而不是全局变量
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:20:31