Łączenie łańcuchów

WorkManager pozwala utworzyć i umieścić w kolejce łańcuch pracy, który określa wiele zależnych zadań i określa kolejność ich wykonywania. Ta funkcja jest szczególnie przydatna, gdy musisz uruchomić kilka zadań w określonej kolejności.

Aby utworzyć łańcuch pracy, możesz użyć funkcji WorkManager.beginWith(OneTimeWorkRequest) lub WorkManager.beginWith(List<OneTimeWorkRequest>), które zwracają instancję WorkContinuation.

Za pomocą WorkContinuation można następnie dodać zależne instancje OneTimeWorkRequest za pomocą then(OneTimeWorkRequest) lub then(List<OneTimeWorkRequest>).

Każde wywołanie funkcji WorkContinuation.then(...) zwraca nowe wystąpienie WorkContinuation. Jeśli dodasz List z OneTimeWorkRequest instancji, te żądania mogą być uruchamiane równolegle.

Na koniec możesz użyć metody WorkContinuation.enqueue() do enqueue() swojego łańcucha WorkContinuation.

Przeanalizujmy przykład. W tym przykładzie skonfigurowane do uruchamiania (potencjalnie równolegle) są skonfigurowane do uruchamiania 3 różne zadania instancji roboczej. Wyniki tych procesów roboczych są następnie łączone i przekazywane do zadania instancji roboczej buforowania. Dane wyjściowe tego zadania są przekazywane do instancji roboczej przesyłania, która 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();

Fuzje danych wejściowych

W przypadku łączenia instancji OneTimeWorkRequest dane wyjściowe nadrzędnych żądań zadań są przekazywane do elementów podrzędnych jako dane wejściowe. Zatem w tym przykładzie dane wyjściowe plantName1, plantName2 i plantName3 byłyby przekazywane jako dane wejściowe do żądania cache.

Do zarządzania danymi wejściowymi z wielu nadrzędnych żądań roboczych usługa WorkManager używa metody InputMerger.

WorkManager udostępnia 2 różne typy znaczników InputMerger:

  • OverwritingInputMerger próbuje dodać do danych wyjściowych wszystkie klawisze ze wszystkich wejść. W przypadku konfliktów zastępuje wcześniej ustawione klucze.

  • ArrayCreatingInputMerger próbuje połączyć dane wejściowe, w razie potrzeby tworzy tablice.

Jeśli potrzebujesz bardziej szczegółowego przypadku użycia, możesz utworzyć własny, przypisując klasyfikację InputMerger.

Nadpisanie danych wejściowych

Domyślną metodą scalania jest OverwritingInputMerger. Jeśli w scalaniu wystąpią konflikty kluczy, najnowsza wartość klucza zastąpi wszystkie wcześniejsze wersje w wynikowych danych wyjściowych.

Jeśli na przykład każde z danych wejściowych „rośliny” ma klucz zgodny z odpowiednimi nazwami zmiennych ("plantName1", "plantName2" i "plantName3"), dane przekazywane do instancji roboczej cache będą miały 3 pary klucz-wartość.

Schemat przedstawiający 3 zadania przekazujące różne dane wyjściowe do następnego zadania w łańcuchu. Wszystkie 3 dane wyjściowe mają różne klucze, dlatego następne zadanie otrzymuje 3 pary klucz-wartość.

W przypadku konfliktu ostatni robot roboczy, który ukończył proces „wygrane”, a jego wartość jest przekazywana do funkcji cache.

Schemat przedstawiający 3 zadania przekazujące dane wyjściowe do następnego zadania w łańcuchu. W tym przypadku 2 z tych zadań generują dane wyjściowe z tym samym kluczem. W rezultacie następne zadanie otrzymuje 2 pary klucz-wartość, przy czym jedna z wyjść powodujących konflikt została usunięta.

Żądania robocze są uruchamiane równolegle, więc nie masz gwarancji co do kolejności ich wykonywania. W powyższym przykładzie plantName1 może zawierać wartość "tulip" lub "elm" zależnie od tego, jaka wartość została zapisana jako ostatnia. Jeśli występuje ryzyko konfliktu kluczy i chcesz zachować wszystkie dane wyjściowe w ramach scalania, lepszym rozwiązaniem będzie ArrayCreatingInputMerger.

Scalanie_tablic

W powyższym przykładzie, ponieważ chcemy zachować dane wyjściowe wszystkich instancji roboczych nazwy fabryki, musimy użyć obiektu 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 paruje każdy klucz z tablicą. Jeśli każdy z kluczy jest unikalny, wynik to seria tablic jednoelementowych.

Schemat przedstawiający 3 zadania przekazujące różne dane wyjściowe do następnego zadania w łańcuchu. Kolejne zadanie przekazuje 3 tablice, po 1 dla każdego klucza wyjściowego. Każda tablica ma jednego element.

Jeśli wystąpią kolizje kluczy, wszystkie odpowiadające im wartości są zgrupowane w tablicy.

Schemat przedstawiający 3 zadania przekazujące dane wyjściowe do następnego zadania w łańcuchu. W tym przypadku 2 z tych zadań generują dane wyjściowe z tym samym kluczem. Następne zadanie przekazuje 2 tablice, po 1 dla każdego klucza. Jedna z tych tablic ma 2 elementy, ponieważ były to 2 wyjściowe dane z tym kluczem.

Łańcuch i stany pracy

Łańcuchy instancji OneTimeWorkRequest są wykonywane sekwencyjnie, dopóki zadanie się powiedzie (tzn. zwróci wartość Result.success()). Żądania zadania mogą podczas działania zakończyć się niepowodzeniem lub zostać anulowane, co ma wpływ na dalsze zależne żądania pracy.

Gdy pierwszy OneTimeWorkRequest zostanie umieszczony w kolejce w łańcuchu żądań, wszystkie kolejne żądania robocze są blokowane do czasu zakończenia pracy pierwszego żądania.

Diagram przedstawiający łańcuch zadań. Pierwsze zadanie znajduje się w kolejce. Wszystkie kolejne zadania są blokowane, dopóki pierwsze nie zostanie ukończone.

Po umieszczeniu w kolejce i spełnieniu wszystkich ograniczeń roboczych zaczyna się działać pierwsze żądanie robocze. Jeśli zadanie zostało ukończone w katalogu głównym OneTimeWorkRequest lub List<OneTimeWorkRequest> (tzn. zwraca Result.success()), kolejna grupa zależnych żądań roboczych zostanie dodana do kolejki.

Diagram przedstawiający łańcuch zadań. Pierwsze zadanie zakończyło się sukcesem, a dwóch jego następców zostaje dodanych do kolejki. Pozostałe zadania zostały zablokowane, ponieważ poprzednie zadania zostały zakończone.

Jeśli każde żądanie zadania zostanie zrealizowane, ten sam wzorzec będzie obowiązywać w pozostałej części łańcucha żądań aż do ukończenia całej pracy w łańcuchu. To najprostszy i najczęściej preferowany przypadek, jednak równie ważne są stany błędu.

Jeśli błąd wystąpi, gdy instancja robocza przetwarza Twoje żądanie robocze, możesz spróbować je wysłać ponownie zgodnie ze zdefiniowaną przez siebie zasadą ponowienia. Ponowienie próby żądania, które jest częścią łańcucha, oznacza, że zostanie ponowiona próba z użyciem dostarczonych danych wejściowych. Nie będzie to miało wpływu na współpracę prowadzoną równolegle.

Diagram przedstawiający łańcuch zadań. Jedno z zadań zakończyło się niepowodzeniem, ale zdefiniowano zasadę ponowienia. Zadanie zostanie ponownie uruchomione po upływie odpowiedniego czasu. Kolejne zadania w łańcuchu będą blokowane, dopóki nie zostaną uruchomione.

Więcej informacji na temat definiowania niestandardowych strategii ponownych prób znajdziesz w zasadach ponawiania i wycofywania.

Jeśli ta zasada ponownych prób jest nieokreślona lub wyczerpana albo w inny sposób dojdziesz do stanu, w którym OneTimeWorkRequest zwraca wartość Result.failure(), to żądanie i wszystkie zależne żądania pracy są oznaczone jako FAILED.

Diagram przedstawiający łańcuch zadań. 1 zadanie zakończyło się niepowodzeniem i nie można go ponowić. W rezultacie wszystkie kolejne zadania w łańcuchu również kończą się niepowodzeniem.

Te same zasady obowiązują w przypadku anulowania polecenia OneTimeWorkRequest. Wszystkie zależne żądania zadań są również oznaczane jako CANCELLED, a ich zadania nie będą wykonywane.

Diagram przedstawiający łańcuch zadań. 1 zadanie zostało anulowane. W związku z tym wszystkie kolejne zadania w łańcuchu również zostaną anulowane.

Pamiętaj, że jeśli dodasz więcej żądań roboczych do łańcucha, który nie powiódł się lub które anulował żądania, nowo dołączone żądanie robocze również zostanie oznaczone odpowiednio FAILED lub CANCELLED. Jeśli chcesz rozszerzyć działanie istniejącego łańcucha, zobacz APPEND_OR_REPLACE w existingWorkPolicy.

Podczas tworzenia łańcuchów żądań pracy zależne żądania pracy powinny określać zasady ponownych prób, aby zawsze były wykonywane w odpowiednim czasie. Nieudane żądania robocze mogą skutkować niepełnymi łańcuchami lub nieoczekiwanym stanem.

Więcej informacji znajdziesz w artykule Anulowanie i zatrzymywanie pracy.