如何使用WorkManager更改定期工作请求的周期而不立即运行?

9
val request = PeriodicWorkRequestBuilder<FooWorker>(1, TimeUnit.DAYS).build()
WorkManager.getInstance().enqueueUniquePeriodicWork(
    "FOO",
    ExistingPeriodicWorkPolicy.REPLACE,
    request
)

上述代码在ApplicationonCreate中运行,以确保请求被排队。然而,这会导致一个问题,即FooWorker将在每次用户启动应用程序时运行,因为ExistingPeriodicWorkPolicy.REPLACE会取消先前的工作并排队新工作,从而使它立即运行。
如果我们改为使用ExistingPeriodicWorkPolicy.KEEP,即使周期或工作者已更改,我们也无法替换该工作。
有没有一种方法可以在当前请求运行后替换请求?
例如,原始请求每天运行1次,新请求每小时运行1次。在下一个原始请求运行后,然后用新请求替换它。
3个回答

8

没有干净利落地实现定期工作的方法。

然而,绝对不需要使用定期工作本身。可以通过在doWork方法结束前安排下一个WorkRequest来轻松实现相同的结构,就在返回Result.SUCCESS之前:

fun doWork(): Result {
  reallyDoWork()
  // Now schedule the next "periodic" work
  val request = OneTimeWorkRequestBuilder<FooWorker>().build()
  WorkManager.getInstance().enqueueUniqueWork(
    "FOO",
    ExistingWorkPolicy.REPLACE,
    request
  )
  return Result.SUCCESS
}

使用此设置,您的ApplicationonCreate()可以安全地使用ExistingWorkPolicy.KEEP,以避免重新安排工作,如果已经有一个WorkRequest排队,并且当排队工作触发时,下一个WorkRequest将排队具有适当的新周期。

我不明白你如何设置开始时间之前的持续时间?还是我理解有误? - Veit

3

现在似乎有一种方法可以使用 enqueueUniquePeriodicWork 替换周期性工作。

  val request = PeriodicWorkRequest.Builder(FooWorker::class.java, 1, TimeUnit.DAYS).build()
  WorkManager.getInstance(appContext)
  .enqueueUniquePeriodicWork(WORK_TAG, ExistingPeriodicWorkPolicy.REPLACE, request)

请确保使用 ExistingPeriodicWorkPolicy 代替 ExistingWorkPolicy


2

如果您想使用 ExistingPeriodicWorkPolicy.KEEP 并且只在需要更改重复间隔时更新 PeriodicWorkRequest,则 WorkManager 中没有解决方案,但是您可以在共享首选项中保存间隔,并检查是否更改了间隔。基于这一点,使用 ExistingPeriodicWorkPolicy.KEEPExistingPeriodicWorkPolicy.REPLACE

public static void enqueue(Context context) {
        Log.d(TAG, "enqueue()");
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
        int repeatInterval = sharedPreferences.getInt("REPEAT_INTERVAL_HOURS", 0);

        PeriodicWorkRequest periodicWorkRequest = new PeriodicWorkRequest
            .Builder(FooWorker.class, REPEAT_INTERVAL_HOURS, TimeUnit.HOURS)
            .build();

        ExistingPeriodicWorkPolicy policy = repeatInterval == REPEAT_INTERVAL_HOURS ? ExistingPeriodicWorkPolicy.KEEP : ExistingPeriodicWorkPolicy.REPLACE;

        sharedPreferences.edit().putInt("REPEAT_INTERVAL_HOURS", REPEAT_INTERVAL_HOURS).apply();

        WorkManager.getInstance(context).enqueueUniquePeriodicWork("fileRemove", policy, periodicWorkRequest);
    }

一旦我在 doWork() 中得到 API 结果,我就会执行相同的操作,但对于我来说,doWork() 是再次调用的。因此它将进入循环。 - Suresh

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