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

使用Kotlin协程递归创建目录时如何判断全部任务执行完成

解决方案

核心问题根因

你原有代码中所有子协程都通过lifecycleScope启动,属于全局生命周期作用域的子任务,和你初始调用createDirectoryStructure所在的协程没有父子绑定关系,因此外层协程不会等待这些子任务执行完成,就会继续往下执行后续代码。

最优修复方案

利用Kotlin协程结构化并发特性,使用coroutineScope包裹递归逻辑,该作用域会自动跟踪所有内部启动的子协程,只有全部子协程执行完成后,coroutineScope块才会返回,完全不需要手动维护计数器或者Job列表。

改后递归方法代码

// directoryBeingBuilt starts as the root directory
private suspend fun createDirectoryStructure(directoryBeingBuiltId: String, directoryBeingBuiltUri: Uri) = coroutineScope {
    // Create subdirectories for all children of directoryBeingBuilt.
    directoryMap[directoryBeingBuiltId]?.forEach { childDirectory ->
        // Create a directory for each childDirectory and set its Uri in directoryMap.
        val currentSubdirectoryUri = getOrCreateDirectory(directoryBeingBuiltUri, childDirectory.directoryName)!!
        childDirectory.directoryUri = currentSubdirectoryUri

        // 直接在当前coroutineScope启动子协程,会被自动纳入作用域跟踪
        launch(Dispatchers.Default) {
            createDirectoryStructure(childDirectory.directoryId, currentSubdirectoryUri)
        }
    }
}

初始调用逻辑无需修改

withContext(Dispatchers.Default) {
    createDirectoryStructure(googleDriveRootDirectoryId.data, backupDirectoryUri)
    // 此处代码会在所有目录创建完成后自动执行
    callYourMethodAfterFinish()
}

原方案不可靠原因说明

  • 计数器方案不可靠通常是因为没有使用线程安全的原子类(如AtomicInteger)维护计数,或者计数增减的时机不对,存在可见性、竞态条件问题
  • 手动维护Job列表的方案需要你每次launch后把Job存入列表,最后调用joinAll()等待所有Job完成,实现繁琐且容易遗漏任务
  • 完全不使用协程相当于串行执行IO操作,耗时自然翻倍,而coroutineScope方案不会损失任何并行性能

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 04:18:00