WorkManager umożliwia tworzenie i umieszczanie w kole zadań w łańcuchu, które określają wiele zależnych od siebie zadań i określają ich kolejność. Ta funkcja jest szczególnie przydatna, gdy chcesz wykonać kilka zadań w określonej kolejności.
Aby utworzyć łańcuch zadań, możesz użyć funkcji WorkManager.beginWith(OneTimeWorkRequest)
lub WorkManager.beginWith(List<OneTimeWorkRequest>)
, które zwracają instancję WorkContinuation
.
Następnie za pomocą WorkContinuation
można dodawać zależne wystąpienia OneTimeWorkRequest
za pomocą then(OneTimeWorkRequest)
lub then(List<OneTimeWorkRequest>)
.
Każde wywołanie funkcji WorkContinuation.then(...)
zwraca nowy egzemplarz funkcji WorkContinuation
. Jeśli dodasz List
wystąpień OneTimeWorkRequest
, te żądania mogą być wykonywane równolegle.
Na koniec możesz użyć metody WorkContinuation.enqueue()
, aby enqueue()
łańcuch WorkContinuation
.
Przeanalizujmy to na przykładzie. W tym przykładzie 3 różne zadania Worker są skonfigurowane do wykonania (opcjonalnie w drodze równoległej). Wyniki tych zadań są następnie łączone i przekazywane do zadania Workera obsługującego buforowanie. W końcu dane wyjściowe tego zadania są przekazywane do procesu przesyłania, który przesyła wyniki na zdalny serwer.
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();
Złączenia danych wejściowych
Gdy połączysz instancje OneTimeWorkRequest
, dane wyjściowe żądań rodzicielskich zostaną przekazane jako dane wejściowe do podrzędnych. W tym przykładzie dane wyjściowe plantName1
, plantName2
i plantName3
są przekazywane jako dane wejściowe do żądania cache
.
Aby zarządzać danymi wejściowymi z wielu nadrzędnych zadań, WorkManager używa interfejsu InputMerger
.
WorkManager udostępnia 2 rodzaje InputMerger
:
OverwritingInputMerger
próbuje dodać wszystkie klucze ze wszystkich danych wejściowych do danych wyjściowych. W przypadku konfliktów zastąpi on wcześniej ustawione klucze.ArrayCreatingInputMerger
próbuje scalić dane wejściowe, tworząc w razie potrzeby tablice.
Jeśli masz bardziej szczegółowy przypadek użycia, możesz napisać własną klasę podrzędną InputMerger
.
OverwritingInputMerger
OverwritingInputMerger
to domyślna metoda scalania. Jeśli podczas scalania wystąpią konflikty kluczy, najnowsza wartość klucza zastąpi wszystkie poprzednie wersje w wynikających danych wyjściowych.
Jeśli np. każdy z wejść plant ma klucz pasujący do nazwy odpowiedniej zmiennej ("plantName1"
, "plantName2"
i "plantName3"
), dane przekazywane instancji roboczej cache
będą zawierać 3 pary klucz-wartość.
Jeśli wystąpi konflikt, „wygrywa” ostatni pracownik, który go ukończył, a jego wartość jest przekazywana do cache
.
Twoje żądania robocze są wykonywane równolegle, więc nie masz gwarancji co do kolejności ich wykonywania. W powyższym przykładzie zmienna plantName1
może zawierać wartość "tulip"
lub "elm"
, w zależności od tego, która wartość została zapisana jako ostatnia. Jeśli istnieje ryzyko konfliktu kluczy i musisz zachować wszystkie dane wyjściowe podczas scalania, ArrayCreatingInputMerger
może być lepszą opcją.
ArrayCreatingInputMerger
W przypadku powyższego przykładu, ponieważ chcemy zachować dane wyjściowe z wszystkich pracowników fabryki o nazwie Workers, powinniśmy użyć 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
łączy każdy klucz z tablicą. Jeśli każdy z kluczy jest niepowtarzalny, wynik to seria tablic jednoelementowych.
Jeśli wystąpią kolizje kluczy, wszystkie odpowiadające im wartości zostaną pogrupowane w tablicy.
Łańcuchowanie i stany pracy
Łańcuchy OneTimeWorkRequest
są wykonywane sekwencyjnie, dopóki ich wykonanie się powiedzie (czyli zwrócą wartość Result.success()
). Żądania o wykonanie pracy mogą się nie udać lub zostać anulowane podczas wykonywania, co ma wpływ na zależne żądania o wykonanie pracy.
Gdy pierwsze OneTimeWorkRequest
zostanie umieszczone w kolejce w łańcuchu żądań pracy, wszystkie kolejne żądania pracy są blokowane do czasu zakończenia pracy związanej z pierwszym żądaniem.
Gdy zadanie zostanie umieszczone w kolejce i spełnione zostaną wszystkie ograniczenia, rozpocznie się wykonywanie pierwszego żądania pracy. Jeśli zadanie zostanie wykonane w korzeniach OneTimeWorkRequest
lub List<OneTimeWorkRequest>
(czyli zwróci wartość Result.success()
), następny zestaw zależnych zadań zostanie umieszczony w kole.
Dopóki każde żądanie pracy zostanie zrealizowane, ten sam wzór będzie się rozprzestrzeniał w dalszej części łańcucha żądań pracy, aż do momentu, gdy wszystkie zadania zostaną ukończone. Chociaż jest to najprostszy i najczęściej preferowany przypadek, stany błędów są równie ważne.
Jeśli podczas przetwarzania Twojego żądania pracy wystąpi błąd, możesz ponownie przesłać to żądanie zgodnie z zdefiniowanymi przez Ciebie zasadami wycofywania. Ponowne próby wykonania żądania, które jest częścią łańcucha, oznaczają, że zostanie ono powtórnie wykonane z podawanymi danymi wejściowymi. Nie wpłynie to na żadne zadania wykonywane równolegle.
Więcej informacji o definiowaniu niestandardowych strategii ponownych prób znajdziesz w artykule Zasady ponownych prób i zmniejszenia częstotliwości.
Jeśli zasada ponownego próbowania jest niezdefiniowana lub wyczerpana albo jeśli w jakiś inny sposób osiągniesz stan, w którym funkcja OneTimeWorkRequest
zwraca wartość Result.failure()
, to żądanie pracy i wszystkie zależne żądania pracy zostaną oznaczone jako FAILED.
.
Ta sama zasada obowiązuje, gdy anulujesz OneTimeWorkRequest
. Wszystkie zależne prośby o wykonanie pracy są też oznaczone jako CANCELLED
i nie będą wykonywane.
Jeśli dodasz więcej próśb o przeniesienie do łańcucha, który nie został zakończony lub został anulowany, nowo dodana prośba zostanie oznaczona odpowiednio jako FAILED
lub CANCELLED
. Jeśli chcesz rozszerzyć zakres obowiązywania istniejących zasad pracy, zapoznaj się z sekcją APPEND_OR_REPLACE
w ExistingWorkPolicy.
Podczas tworzenia łańcuchów żądań pracy należy zdefiniować zasady ponownych prób, aby mieć pewność, że zadania są zawsze wykonywane w odpowiednim czasie. Nieudane żądania pracy mogą spowodować niepełne łańcuchy lub nieoczekiwany stan.
Więcej informacji znajdziesz w artykule Anulowanie i zatrzymywanie pracy.