WorkManager позволяет создавать и ставить в очередь цепочку задач, которая определяет несколько зависимых задач и порядок их выполнения. Эта функция особенно полезна, когда вам нужно запустить несколько задач в определенном порядке.
Чтобы создать цепочку работ, можно использовать WorkManager.beginWith(OneTimeWorkRequest)
или WorkManager.beginWith(List<OneTimeWorkRequest>)
, каждый из которых возвращает экземпляр WorkContinuation
.
Затем WorkContinuation
можно использовать для добавления зависимых экземпляров OneTimeWorkRequest
с помощью then(OneTimeWorkRequest)
или then(List<OneTimeWorkRequest>)
.
Every invocation of the WorkContinuation.then(...)
returns a new instance of WorkContinuation
. If you add a List
of OneTimeWorkRequest
instances, these requests can potentially run in parallel.
Наконец, вы можете использовать метод WorkContinuation.enqueue()
для enqueue()
вашей цепочки WorkContinuation
.
Рассмотрим пример. В этом примере настроено выполнение трёх различных заданий 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 .
При создании цепочек рабочих запросов зависимые рабочие запросы должны определять политики повторных попыток, чтобы гарантировать своевременное выполнение работ. Невыполненные рабочие запросы могут привести к неполным цепочкам и/или непредвиденным состояниям.
Более подробную информацию см. в разделе Отмена и прекращение работ .