【问题标题】:WorkManager existing work policy APPEND_OR_REPLACE doesn't behave as expectedWorkManager 现有工作策略 APPEND_OR_REPLACE 未按预期运行
【发布时间】:2021-11-01 22:29:39
【问题描述】:

我目前正在使用来自androidx.work:work-runtime-ktx:2.5.0CoroutineWorker

我想要实现的是:

  1. 使用beginUniqueWork 和相同的uniqueWorkName 排队工作人员,使用策略ExistingWorkPolicy.APPEND_OR_REPLACE
  2. 这将按顺序运行工作程序,如果工作失败或被取消,预期的行为将是,根据documentation

如果有失败或取消的先决条件,这些先决条件将被删除,新指定的工作是新序列的开始。

发生的情况是,如果前一个工作人员也被取消(或失败),所有或排队的工作人员都会被取消。这应该是ExistingWorkPolicy.APPEND 而不是ExistingWorkPolicy.APPEND_OR_REPLACE 的预期行为。

任何想法为什么会发生这种情况?如何避免排队的唯一工作人员也被取消?

【问题讨论】:

  • 我也在寻找这个问题的答案,但找不到。暂时,无论如何我都使用了 Worker 的返回结果成功,因此链继续。我建议你也在这里查看:twitter.com/danlew42/status/1214562086585421826?s=20
  • 感谢您的帮助,不幸的是,这不适用于我的用例,因为我还希望能够取消独特的工作。在这种情况下,返回总是成功将无济于事。
  • stackoverflow.com/a/71657305/847661 可能有助于解释为什么会发生这种情况。

标签: android android-workmanager


【解决方案1】:

APPEND_OR_REPLACE 的名字有误导性,看了这个你会认为这个Worker 会在失败的情况下替换之前的worker,或者如果是RUNNING 则追加,这是错误的!

APPEND_OR_REPLACE 表示将此工作器附加到正在运行的 或如果前一个失败,则用新链替换链(创建一个新链并重新开始,这就像一个硬重置)

伪代码

if (getChainWithUniqueTag(TAG).status == CANCELLED || FAILED) {
    createNewChine()
}
addRequestToChainWithTag(TAG,request)

现在应该更有意义了,它是关于当前 chain 的状态,而不是 Work


为了进一步确认这一点,尝试使用唯一名称启动一个worker1,然后使其失败(通过调用Result.failure)然后创建另一个具有相同唯一名称的APPENDworker2,worker2 将直接失败在开始之前,因为它属于失败的链。

如果您尝试相同的场景但使用APPEND_OR_REPLACEworker2 将启动一个新链并继续正常工作。

考虑这个例子:

val request1 = OneTimeWorkRequestBuilder<SleepWorker>()
                .setInputData(workDataOf(KEY_BREAK_AT to 5))
                .build()

val request2 = OneTimeWorkRequestBuilder<SleepWorker>()
                .build()
workManager.enqueueUniqueWork(
    TAG,
    ExistingWorkPolicy.APPEND_OR_REPLACE,
    request1
)
// Infinite loop
while (workManager.getWorkInfoById(request1.id).get().state == WorkInfo.State.RUNNING){}

workManager.enqueueUniqueWork(
    TAG,
    ExistingWorkPolicy.APPEND_OR_REPLACE,
    request2
)

SleepWorker

class SleepWorker(context: Context, parameters: WorkerParameters) :
        CoroutineWorker(context, parameters) {
        override suspend fun doWork(): Result {
            val breakAt = inputData.getInt(KEY_BREAK_AT,-1)
            repeat(10) {
                if(it == breakAt) return Result.failure()
                println("$it")
                delay(1000L)
            }
            return Result.success()
        }
}

现在这种情况下request1会失败,然后我们启动request2会正常启动,因为FLAG是APPEND_OR_REPLACE, 如果标志是APPEND,那么request2 将失败。

PS:尝试在无限 while 循环之前将第二个 enqueueUniqueWork 移动到 request2 之前,request2 也会失败。有道理吗?

因为当我们调用enqueueUniqueWork 时,链条当时很好,因此作业已成功添加到该链条中。

【讨论】:

    猜你喜欢
    • 2012-11-14
    • 2019-07-30
    • 2021-07-09
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    相关资源
    最近更新 更多