WorkManager 现有工作策略 APPEND_OR_REPLACE 未按预期运行

xat*_*okk 9 android android-workmanager

我目前正在使用CoroutineWorkerfrom androidx.work:work-runtime-ktx:2.5.0.

我想要实现的是:

  1. 入队工人与beginUniqueWork和相同uniqueWorkName,与政策ExistingWorkPolicy.APPEND_OR_REPLACE
  2. 这将按顺序运行工作人员,如果工作失败或被取消,根据文档,预期行为将

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

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

预期行为 -> 实际行为

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

ike*_*fah 8

的名称APPEND_OR_REPLACE具有误导性,通过阅读本文,您会认为这Worker会在发生故障时替换以前的工作程序,或者如果正在运行则附加,这是错误的!

APPEND_OR_REPLACE意味着将此工作人员追加到正在运行的中,或者如果前一个工作失败,则用新的链替换该工作人员(创建一个新的链并重新开始,这就像硬重置)

伪代码

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

Run Code Online (Sandbox Code Playgroud)

现在它应该更有意义,它是关于当前链的状态而不是工作


为了进一步确认这一点,尝试使用唯一名称启动一个worker1,然后使其失败(通过调用Result.failure),然后创建另一个具有APPEND相同唯一名称的worker2,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
)

Run Code Online (Sandbox Code Playgroud)

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()
        }
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 这解释了这种行为。但是是否有官方文档可以解释链的这种行为?这似乎是隐藏的,我找不到任何官方文档。 (2认同)