WorkManager позволяет создавать и ставить в очередь цепочку работ, которая определяет несколько зависимых задач и порядок их выполнения. Эта функция особенно полезна, когда вам нужно запустить несколько задач в определенном порядке.
Чтобы создать цепочку работ, можно использовать WorkManager.beginWith(OneTimeWorkRequest)
или WorkManager.beginWith(List<OneTimeWorkRequest>)
, каждый из которых возвращает экземпляр WorkContinuation
.
Затем WorkContinuation
можно использовать для добавления зависимых экземпляров OneTimeWorkRequest
с помощью then(OneTimeWorkRequest)
или then(List<OneTimeWorkRequest>)
.
Каждый вызов WorkContinuation.then(...)
возвращает новый экземпляр WorkContinuation
. Если вы добавите List
экземпляров OneTimeWorkRequest
, эти запросы потенциально могут выполняться параллельно.
Наконец, вы можете использовать метод WorkContinuation.enqueue()
для enqueue()
вашей цепочки WorkContinuation
.
Давайте рассмотрим пример. В этом примере 3 разных задания Worker настроены на выполнение (потенциально параллельно). Результаты этих Worker затем объединяются и передаются в кэширующее задание Worker. Наконец, вывод этого задания передается в Worker загрузки, который загружает результаты на удаленный сервер.
Котлин
WorkManager.getInstance(myContext) // Candidates to run in parallel .beginWith(listOf(plantName1, plantName2, plantName3)) // Dependent work (only runs after all previous work in chain) .then(cache) .then(upload) // Call enqueue to kick things off .enqueue()
Ява
WorkManager.getInstance(myContext) // Candidates to run in parallel .beginWith(Arrays.asList(plantName1, plantName2, plantName3)) // Dependent work (only runs after all previous work in chain) .then(cache) .then(upload) // Call enqueue to kick things off .enqueue();
Входные слияния
Когда вы связываете экземпляры OneTimeWorkRequest
, выходные данные родительских рабочих запросов передаются в качестве входных данных для дочерних. Таким образом, в приведенном выше примере выходные данные plantName1
, plantName2
и plantName3
будут переданы в качестве входных данных для запроса cache
.
Для управления входными данными из нескольких родительских рабочих запросов WorkManager использует InputMerger
.
WorkManager предоставляет два различных типа InputMerger
:
OverwritingInputMerger
пытается добавить все ключи из всех входов в выход. В случае конфликтов он перезаписывает ранее установленные ключи.ArrayCreatingInputMerger
пытается объединить входные данные, создавая массивы при необходимости.
Если у вас более конкретный вариант использования, вы можете написать свой собственный, создав подкласс InputMerger
.
ПерезаписьInputMerger
OverwritingInputMerger
— метод слияния по умолчанию. Если при слиянии возникают конфликты ключей, то последнее значение ключа перезапишет все предыдущие версии в результирующих выходных данных.
Например, если входные данные растений имеют ключ, соответствующий именам соответствующих переменных ( "plantName1"
, "plantName2"
и "plantName3"
), то данные, переданные в cache
обработчик, будут иметь три пары «ключ-значение».
Если возникает конфликт, то последний завершивший работу воркер «побеждает», и его значение передается в cache
.
Поскольку ваши рабочие запросы выполняются параллельно, у вас нет гарантий относительно порядка, в котором они выполняются. В приведенном выше примере plantName1
может содержать значение "tulip"
или "elm"
в зависимости от того, какое значение записано последним. Если у вас есть вероятность конфликта ключей и вам нужно сохранить все выходные данные при слиянии, то ArrayCreatingInputMerger
может быть лучшим вариантом.
ArrayCreatingInputMerger
Для приведенного выше примера, учитывая, что мы хотим сохранить выходные данные всех рабочих с именем завода, нам следует использовать ArrayCreatingInputMerger
.
Котлин
val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>() .setInputMerger(ArrayCreatingInputMerger::class) .setConstraints(constraints) .build()
Ява
OneTimeWorkRequest cache = new OneTimeWorkRequest.Builder(PlantWorker.class) .setInputMerger(ArrayCreatingInputMerger.class) .setConstraints(constraints) .build();
ArrayCreatingInputMerger
спаривает каждый ключ с массивом. Если каждый из ключей уникален, то ваш результат — это серия одноэлементных массивов.
Если есть какие-либо коллизии ключей, то все соответствующие значения группируются в массив.
Цепочки и рабочие статусы
Цепочки OneTimeWorkRequest
выполняются последовательно до тех пор, пока их работа завершается успешно (то есть они возвращают Result.success()
). Запросы на работу могут завершиться неудачей или быть отменены во время выполнения, что оказывает нисходящее влияние на зависимые запросы на работу.
Когда первый запрос OneTimeWorkRequest
ставится в очередь в цепочке рабочих запросов, все последующие рабочие запросы блокируются до тех пор, пока работа по этому первому запросу не будет завершена.
После постановки в очередь и удовлетворения всех ограничений работы первый запрос работы начинает выполняться. Если работа успешно завершена в корневом OneTimeWorkRequest
или List<OneTimeWorkRequest>
(то есть, он возвращает Result.success()
), то следующий набор зависимых запросов работы будет поставлен в очередь.
Пока каждый запрос на работу завершается успешно, этот же шаблон распространяется на всю остальную часть вашей цепочки запросов на работу, пока вся работа в цепочке не будет завершена. Хотя это самый простой и часто предпочтительный случай, состояния ошибок так же важны для обработки.
Если во время обработки вашего рабочего запроса возникает ошибка, вы можете повторить этот запрос в соответствии с политикой отсрочки, которую вы определяете . Повтор запроса, который является частью цепочки, означает, что только этот запрос будет повторен с предоставленными ему входными данными. Любая работа, выполняемая параллельно, не будет затронута.
Дополнительную информацию об определении пользовательских стратегий повтора см. в разделе Политика повтора и отсрочки .
Если политика повторных попыток не определена или исчерпана, или вы иным образом достигли некоторого состояния, в котором OneTimeWorkRequest
возвращает Result.failure()
, то этот рабочий запрос и все зависимые рабочие запросы помечаются как FAILED.
Та же логика применяется при отмене OneTimeWorkRequest
. Любые зависимые рабочие запросы также помечаются как CANCELLED
, и их работа не будет выполнена.
Обратите внимание, что если вы хотите добавить больше рабочих запросов в цепочку, которая не удалась или отменила рабочие запросы, то ваш новый добавленный рабочий запрос также будет помечен как FAILED
или CANCELLED
соответственно. Если вы хотите расширить работу существующей цепочки, см. APPEND_OR_REPLACE
в ExistingWorkPolicy .
При создании цепочек рабочих запросов зависимые рабочие запросы должны определять политики повторных попыток, чтобы гарантировать, что работа всегда будет завершена своевременно. Неудачные рабочие запросы могут привести к неполным цепочкам и/или неожиданному состоянию.
Более подробную информацию см. в разделе Отмена и прекращение работы .