使用Work Manager时,BackoffPolicy.EXPONENTIAL和BackoffPolicy.LINEAR有什么区别?

11

在我阅读过的文档中,没有任何官方文档解释这两种模式的用法和机制。它们如何工作?它们解决了什么问题?

如果有人能为我简化一下,我会很感激,因为我已经测试过两种模式,但并没有发现什么有趣的东西。如果你问我,我会说OneTimeWorkRequest.setBackoffCriteria()对工作没有影响。

这里是我的代码,

@Override
public void doSomethingUseful(String order) {

    Constraints constraint = new Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build();

    Data data = new Data.Builder()
            .putString("order", order)
            .build();

    OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(OrderSenderWorker.class)
            .setConstraints(constraint)
            .setInputData(data)
            .setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 15, TimeUnit.SECONDS)
            .build();

    WorkManager.getInstance().beginUniqueWork("refresh-order", ExistingWorkPolicy.REPLACE, oneTimeWorkRequest).enqueue();

}

Worker类中,每当我做错什么时,在doWork()方法中我会返回WorkerResult.RETRY

提前感谢。


2个回答

12
考虑到WorkManager使用运行尝试次数作为参考,对于15秒的BackoffPolicy,如下所示:
  • 对于线性: 工作开始时间 + (15 * 运行尝试次数)

  • 对于指数: 工作开始时间 + Math.scalb(15, 运行尝试次数 - 1)

工作开始时间是工作第一次执行时(第1次运行尝试)。 运行尝试次数是WorkManager尝试执行特定工作的次数。
还要注意,最大延迟将被限制在WorkRequest.MAX_BACKOFF_MILLIS
请注意,只有在返回WorkerResult.RETRY并指定工作需要重试时,才会进行重试。

1
因此,对于线性重试,将在15秒的时间间隔内进行重试,乘以总运行尝试次数,并加上工作开始时间。只有在通过返回WorkerResult.RETRY状态完成工作时,重试才会自动发生。如果您不想重试特定的工作,则返回WorkerResult.SUCCESS或FAILURE。 - PerracoLabs
1
如果您想让一个工作每15秒运行一次,那么您需要使用PeriodicWorkRequest。setBackoffCriteria用于在需要指定重试速率时使用。如果在您的代码逻辑中,由于任何原因导致工作失败(没有网络、磁盘空间不足等),则返回RETRY状态,WorkManager将使用BackoffCriteria计算下一次重试时间,这是不会以恒定速率进行的,因为延迟(指数或线性)将乘以运行尝试计数。如果我理解有误,请告诉我。 - PerracoLabs
1
我看到你的代码中有一个ExistingWorkPolicy.REPLACE。确保在重试之前等待并不再执行此代码逻辑,因为ExistingWorkPolicy.REPLACE将使先前排队的工作被丢弃,因此没有15秒的重试。另外,为了确保,请获取最新的WorkManager版本。此外,正如所解释的那样,它不会每15秒发生一次,它将发生15秒*工作已经重试的次数(对于线性),而对于指数将更长。 - PerracoLabs
1
忘了提到,如果你不返回WorkerResult.RETRY,setBackoffCriteria将不起作用。所以最好的做法是设置一些跟踪和调试,以便在你期望返回WorkerResult.RETRY时进行检查。并且请记住,它不会每15秒发生一次,请查看答案公式以了解重试时间是如何计算的。 - PerracoLabs
1
你已经获取最新的WorkManager版本了吗?关于此问题已有一个错误报告,已被修复:https://issuetracker.google.com/issues/112929917 - PerracoLabs
显示剩余7条评论

1
考虑一下,如果您正在访问服务器上的API,如果服务器返回特定状态,则在一定时间后再次访问API。
现在,为了控制任何两个API调用之间的时间间隔,您可以使用BackoffPolicy。
如果您使用BackoffPolicy.LINEAR,则间隔时间将线性增加,直到达到阈值。
或者,如果您使用BackoffPolicy.EXPONENTIAL,则间隔时间将呈指数增长,直到达到阈值。

您的阈值是否表示最大退避延迟持续时间? - Mehdi Jahed Manesh
根据您的声明,如您所见我的代码,我的阈值为15秒,我的重试策略必须在15秒后停止,对吗?但是它在15秒后仍然继续重试。 - Mehdi Jahed Manesh
1
这里的15不是最大的退避延迟时间。setBackoffCriteria(backoffPolicy: BackoffPolicy, backoffDelay: Long, timeUnit: TimeUnit)中的backoffDelay指的是从15开始指数增加的间隔时间。 - thegoodguy
@thegoodguy 这个阈值时间是确切的还是基于我们的时间配置来定义的? - Nigam Patro

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