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
.
Давайте посмотрим на пример. В этом примере настроено выполнение трех разных рабочих заданий (возможно, параллельно). Результаты этих рабочих процессов затем объединяются и передаются в задание кэширующего рабочего процесса. Наконец, выходные данные этого задания передаются в 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 .
При создании цепочек рабочих запросов зависимые рабочие запросы должны определять политики повтора, чтобы гарантировать, что работа всегда выполняется своевременно. Неудачные рабочие запросы могут привести к неполным цепочкам и/или неожиданному состоянию.
Для получения дополнительной информации см. Отмена и остановка работы .