如何使用WorkManager下载包含图片视频的数据集并获取详细进度
基于WorkManager实现批量下载的进度统计与完整性校验方案
问题1:多文件下载整体进度统计与UI同步
- 先确定总任务基准值:提交下载任务前,遍历当前待下载对象的所有资源URL,调用HTTP HEAD请求获取每个资源的
Content-Length,累加得到总任务字节数,也可以额外统计总文件数作为第二统计维度,将这两个值存入WorkRequest的InputData中。 - 实现线程安全的进度上报逻辑:如果使用
CoroutineWorker,直接调用setProgress()方法把当前已完成数据实时存入WorkManager的进度存储。多文件并行下载时用AtomicLong这类线程安全的计数器存储已完成字节数,每个文件下载流每读取一批字节就更新计数器,更新后同步调用setProgress上报最新进度。 - UI层监听进度:通过
WorkManager.getInstance(context).getWorkInfoByIdLiveData(workRequest.id)观察WorkInfo状态变化,从WorkInfo的progress字段中取出已完成值和总任务值,计算百分比后直接更新UI即可。
小提示:如果服务端不支持HEAD请求,也可以在第一个GET请求读取响应头时动态获取
Content-Length更新总任务大小,第一次上报进度时把总大小同步给UI即可。
问题2:下载完整性校验
- 给每个下载对象生成唯一标识,比如用对象ID的哈希值作为本地专属存储目录名,该对象的所有文本数据、资源文件都存入这个目录,避免和其他对象数据混淆。
- 提交下载任务前,在该对象的专属目录下生成一份下载清单文件,内容包含:当前对象的所有资源URL、每个资源的预期文件大小、服务端返回的文件哈希值(如有)、文本内容的哈希值。
- 所有下载任务执行完成后统一跑校验逻辑:
- 校验本地存储的文本内容哈希和清单中的值是否一致
- 遍历清单中的所有资源,检查本地对应路径的文件是否存在、文件大小是否符合预期,有哈希值的话再比对文件哈希
- 所有项匹配则标记该对象下载状态为
已完成,否则标记为下载失败,同时记录缺失/损坏的文件列表,后续重试可以直接跳过已完成文件,只下载异常部分
- 如果下载过程中出现网络、IO异常导致文件下载中断,直接在Worker的返回值里返回
Result.retry(),WorkManager会按照你配置的退避策略自动重试。
核心逻辑代码示例
class BatchDownloadWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) { // 线程安全的已完成字节计数器 private val completedBytes = AtomicLong(0L) override suspend fun doWork(): Result { val totalBytes = inputData.getLong("TOTAL_BYTES", 0L) val resourceList = inputData.getStringArray("RESOURCE_LIST") ?: emptyArray() // 并行下载资源 coroutineScope { resourceList.forEach { url -> async { downloadFile(url) { chunkBytes -> // 累加已下载字节 val current = completedBytes.addAndGet(chunkBytes) // 上报进度 setProgress(workDataOf( "COMPLETED_BYTES" to current, "TOTAL_BYTES" to totalBytes )) } } } } // 执行完整性校验 val isAllComplete = verifyAllDownloadFiles() return if (isAllComplete) Result.success() else Result.retry() } }
内容的提问来源于stack exchange,提问作者Rajnikant B
相关产品推荐
相关产品推荐

