如何立即使用 WorkManager 运行 更改周期性工作请求周期?

How to change periodic work request period without it running immediately using WorkManager?

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

上面的代码是 运行 in onCreate of Application 以确保请求入队。但是,这会导致一个问题,即每次用户启动应用程序时 FooWorker 都会 运行,因为 ExistingPeriodicWorkPolicy.REPLACE 取消以前的工作并将新工作加入队列,这会导致它立即 运行。

如果我们改成ExistingPeriodicWorkPolicy.KEEP,即使更换工期或工人,我们也无法更换工作。

有没有办法替换当前请求运行ning之后的请求?

例如,原始请求运行每天1次,新请求是每小时1次。下一个原始请求运行后,再替换为新的请求

没有办法以干净的方式通过周期性工作准确地完成您想要的事情。

但是,完全没有必要使用周期性工作本身。通过在 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 将在适当的新周期内排队。

现在看来有一种方法可以用 enqueueUniquePeriodicWork 替换周期性工作。

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

确保您传递的是 ExistingPeriodicWorkPolicy 而不是 ExistingWorkPolicy

如果你想使用ExistingPeriodicWorkPolicy.KEEP并且只在你想改变重复间隔时更新PeriodicWorkRequest,WorkManager没有解决方案,但你可以在sharedPreferences中保存间隔并检查间隔是否被改变。并基于此使用 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);
    }