Как изменить период периодического запроса на работу, не выполняя его немедленно, с помощью WorkManager?

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

Приведенный выше код выполняется в onCreate из Application, чтобы запрос был поставлен в очередь. Однако это вызовет проблему, когда FooWorker будет запускаться каждый раз, когда пользователь запускает приложение, потому что ExistingPeriodicWorkPolicy.REPLACE отменяет предыдущую работу и ставит новую работу в очередь, что приводит к ее немедленному запуску.

Если мы перейдем на ExistingPeriodicWorkPolicy.KEEP, мы не сможем заменить работу даже при смене периода или работника.

Есть ли способ заменить запрос после выполнения текущего?

Например, исходный запрос выполняется 1 раз в день, а новый запрос - 1 раз в час. После выполнения следующего запроса происхождения замените его новым запросом.


person Joshua    schedule 10.10.2018    source источник


Ответы (3)


Невозможно делать то, что вы хотите, с помощью периодической работы чисто.

Однако использовать саму периодическую работу совершенно не нужно. Эту же структуру можно легко реализовать, запланировав следующий WorkRequest в конце вашего doWork метода, прямо перед возвратом 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
}

При такой настройке ваш onCreate() из Application может безопасно использовать ExistingWorkPolicy.KEEP, чтобы избежать перепланирования работы, если у вас уже есть WorkRequest в очереди, и когда срабатывает эта поставленная в очередь работа, следующий WorkRequest будет поставлен в очередь с соответствующим новым периодом.

person ianhanniballake    schedule 10.10.2018

Похоже, теперь есть способ заменить периодическую работу на enqueueUniquePeriodicWork.

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

Убедитесь, что вы передаете ExistingPeriodicWorkPolicy вместо ExistingWorkPolicy

person meh    schedule 10.04.2019

Если вы хотите использовать ExistingPeriodicWorkPolicy.KEEP и обновлять PeriodicWorkRequest только тогда, когда вы хотите изменить интервал повтора, решения от WorkManager нет, но вы можете сохранить интервал в sharedPreferences и проверить, был ли изменен интервал. И на основе этого использовать ExistingPeriodicWorkPolicy.KEEP или ExistingPeriodicWorkPolicy.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);
    }
person Šemsudin Tafilović    schedule 26.09.2020
comment
Я делаю то же самое, когда получаю результат API в doWork (), но для меня doWork () снова вызывает. Итак, это будет цикл. - person Suresh; 08.07.2021