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

WorkManager进度事件未传递:监听Worker完成状态始终失败

问题描述

我尝试监听Worker的工作完成状态,Worker代码如下:

override suspend fun doWork(): Result = withContext(Dispatchers.IO) {
    val collectionName = checkNotNull(inputData.getString(COLLECTION_NAME_KEY))
    val uris = checkNotNull(inputData.getStringArray(URIS_KEY)?.toList()?.map { Uri.parse(it) })

    setForegroundAsync(createForegroundInfo())

    val collectionId = Random(System.currentTimeMillis()).nextLong()
    val comics = saveFileAndCreateComics(collectionId, uris)
    val collection = ComicCollection(id = collectionId, name = collectionName)

    database.comicCollectionDao().insert(collection, comics)

    setProgress(workDataOf(IMPORT_FINISHED to true)) // 传递完成事件

    Result.success()
}

监听代码:

val workManager = WorkManager.getInstance(context)

val data = Data.Builder()
    .putString(ImportFilesWorker.COLLECTION_NAME_KEY, collectionName)
    .putStringArray(ImportFilesWorker.URIS_KEY, uris.map { it.toString() }.toTypedArray())
    .build()

val uploadWorkRequest = OneTimeWorkRequestBuilder<ImportFilesWorker>()
    .setInputData(data)
    .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
    .build()

workManager.enqueueUniqueWork(WORK_NAME, ExistingWorkPolicy.KEEP, uploadWorkRequest)

WorkManager.getInstance(context)
    .getWorkInfoByIdLiveData(uploadWorkRequest.id)
    .observeForever { workInfo ->
        workInfo?.progress?.let {
            val finished = it.getBoolean(IMPORT_FINISHED, false) // 监听完成事件
            Timber.e("FINISHED = $finished")
        }
    }

但日志始终显示FINISHED = false。我遗漏了什么?

更新:同时记录WorkInfo状态后,日志输出如下:

STATE = ENQUEUED
FINISHED = false
STATE = RUNNING
FINISHED = false
STATE = SUCCEEDED
FINISHED = false

解决方法

1. 优先通过WorkInfo状态判断任务完成

WorkManager本身就通过WorkInfo.State标识任务状态,当状态变为SUCCEEDED时,就说明任务已完成,这是最可靠的判断方式,无需依赖progress传递标志。修改监听代码如下:

WorkManager.getInstance(context)
    .getWorkInfoByIdLiveData(uploadWorkRequest.id)
    .observeForever { workInfo ->
        workInfo?.let {
            when (it.state) {
                WorkInfo.State.SUCCEEDED -> {
                    Timber.e("任务已完成")
                    // 在这里处理任务完成后的逻辑
                }
                WorkInfo.State.RUNNING -> {
                    val finished = it.progress.getBoolean(ImportFilesWorker.IMPORT_FINISHED, false)
                    Timber.e("FINISHED = $finished")
                }
                else -> Timber.e("当前任务状态:${it.state}")
            }
        }
    }

2. 检查常量定义一致性

确认IMPORT_FINISHED常量在Worker和监听代码中的字符串值完全一致,避免拼写错误导致无法读取正确的progress值。比如在Worker中定义:

const val IMPORT_FINISHED = "import_finished"

监听代码中必须直接引用这个常量,而非重新定义同名但值不同的常量:

val finished = it.progress.getBoolean(ImportFilesWorker.IMPORT_FINISHED, false)

3. 确保setProgress执行完成后再返回Result

虽然setProgress是挂起函数会等待执行完成,但如果任务执行速度极快,可能存在WorkManager还未同步progress状态,Worker就已结束的情况。可以尝试在setProgress后添加短暂延迟(仅用于排查,不推荐作为常规方案):

setProgress(workDataOf(IMPORT_FINISHED to true))
delay(100) // 短暂延迟确保状态同步
Result.success()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 16:00:59