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 (возможно, параллельно). Результаты работы этих рабочих ВМ объединяются и передаются в задание рабочей ВМ, выполняющей кеширование. Наконец, выходные данные этой задачи передаются в Worker, который загружает результаты на удаленный сервер.
Kotlin
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()
Java
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.
OverwritingInputMerger
OverwritingInputMerger – метод объединения по умолчанию. Если при объединении возникнут конфликты ключей, то последнее значение ключа перезапишет все предыдущие версии в итоговых выходных данных.
Например, если у каждого входного значения завода есть ключ, соответствующий названию переменной ("plantName1", "plantName2" и "plantName3"), то данные, переданные исполнителю cache, будут содержать три пары "ключ-значение".
Если возникает конфликт, то "побеждает" последний завершивший работу исполнитель, и его значение передается в cache.
Поскольку запросы на выполнение заданий обрабатываются параллельно, порядок их выполнения не гарантируется. В примере выше plantName1 может иметь значение "tulip" или "elm" в зависимости от того, какое значение было записано последним. Если есть вероятность конфликта ключей и вам нужно сохранить все выходные данные при объединении, лучше использовать ArrayCreatingInputMerger.
ArrayCreatingInputMerger
В приведенном выше примере, поскольку мы хотим сохранить выходные данные всех исполнителей, связанных с названиями растений, следует использовать ArrayCreatingInputMerger.
Kotlin
val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>() .setInputMerger(ArrayCreatingInputMerger::class) .setConstraints(constraints) .build()
Java
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.
При создании цепочек рабочих запросов для зависимых запросов следует определить правила повторных попыток, чтобы обеспечить своевременное выполнение работы. Неудачные запросы на работу могут привести к неполным цепочкам и/или неожиданному состоянию.
Подробнее об отмене и остановке работы…