WorkManager的OneTimeWorkRequest有哪些重试策略/机制?

28

我有以下一次性工作者。

// Create a Constraints that defines when the task should run
Constraints constraints = new Constraints.Builder()
        .setRequiredNetworkType(NetworkType.UNMETERED)
        .setRequiresBatteryNotLow(true)
        // Many other constraints are available, see the
        // Constraints.Builder reference
        .build();

OneTimeWorkRequest oneTimeWorkRequest =
        new OneTimeWorkRequest.Builder(SyncWorker.class)
                .setConstraints(constraints)
                .addTag(SyncWorker.TAG)
                .build();

根据https://developer.android.com/topic/libraries/architecture/workmanager
// (Returning RETRY tells WorkManager to try this task again
// later; FAILURE says not to try again.)

我在想,如果SyncWorker不断返回RETRY,那么WorkManager的重试策略是什么?例如,WorkManager的最大重试次数是多少?文档没有明确说明。
3个回答

36
默认情况下,使用的是 BackoffPolicy.EXPONENTIAL。只有当您通过返回 WorkerResult.RETRY 要求我们进行 RETRY 或者您所需的 Worker 的约束条件现在不满足时,我们才会重试。例如,如果您需要一个 NETWORK 约束条件,现在设备失去了活动的 Network 连接,则 Worker 将停止并自动重试(当约束条件得到满足时)。
有关更多信息,请查看文档

很奇怪,因为我曾经遇到过约束条件未满足的情况,但在约束条件得到满足后,它会推迟工作程序的执行。对此行为有何见解? - remedy.
@remedy 你可以在 doWork 方法中返回 RETRY - sam_k
@remedy 是的,但它会在一段时间后执行。如果您想立即执行某些操作,则必须使用startForeGroundService。 - sam_k
1
@Rahul 那么在队列中的最后一个工作人员完成后,如果需要重新尝试一些唯一(命名)的工作该怎么办?我有 N 个相同类型的工作人员可能需要重试,如果某些信息尚不可用,但如果其中一个失败,则需要在其他队列成员尝试获取其信息之前立即重试,以避免同一工作人员“永远”失败,直到其特定信息可用为止。是否可以设计这种工作流程? - Luan
1
但是如果没有任何更改,它会一直重试还是在10分钟后停止? - RamPrasadBismil
显示剩余2条评论

21

以下示例在捕获异常后重试3次,然后退出。

class RepeatWorker(context : Context, params : WorkerParameters)
    : Worker(context, params) {

    private fun doSomeThing() {
        // do something
    }

    override fun doWork(): Result {

        if (runAttemptCount > 3) {
            return Result.failure()
        }

        try {
            doSomeThing()
        }
        catch (e: Exception) {
            e.printStackTrace()
            return Result.retry()
        }
        return Result.success()
    }
}

注意:默认的退避策略是指数级的,在这种情况下,第一次重试时间为30秒(最小重试间隔为10秒,最大重试间隔不超过18000秒/5小时)。

fun start() : LiveData<WorkInfo> {
    val WORK_NAME = "SingleBackupWorker"

    val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

    val work = OneTimeWorkRequestBuilder<BackupWorker>()
            .setConstraints(constraints)
            .setInitialDelay(5, TimeUnit.SECONDS)
            .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 1, TimeUnit.MINUTES)
            .build()

    WorkManager.getInstance().enqueueUniqueWork(WORK_NAME, ExistingWorkPolicy.REPLACE, work)

    return WorkManager.getInstance().getWorkInfoByIdLiveData(work.id)
}

1
嘿,你从哪里获取有关最大重试期的信息? - Shivam Pokhriyal
https://developer.android.com/topic/libraries/architecture/workmanager/how-to/define-work - Renaud
文档中真的应该有一个关于如何使用runAttemptCount来限制重试次数的示例。 - lasec0203
“最大重试时间永远不会超过18000秒/5小时”这是误导性的。您不能为退避延迟设置超过5小时,但工作程序将指数级地无限重试,直到成功或失败为止。 - JacksOnF1re

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接