WorkManager umożliwia tworzenie i dodawanie do kolejki łańcucha zadań, który określa wiele zależnych zadań i definiuje kolejność ich wykonywania. Ta funkcja jest szczególnie przydatna, gdy musisz uruchomić kilka zadań w określonej kolejności.
Aby utworzyć łańcuch zadań, możesz użyć metody WorkManager.beginWith(OneTimeWorkRequest) lub WorkManager.beginWith(List<OneTimeWorkRequest>), które zwracają instancję WorkContinuation.
Następnie można użyć WorkContinuation, aby dodać zależne instancje OneTimeWorkRequest za pomocą then(OneTimeWorkRequest) lub then(List<OneTimeWorkRequest>).
Każde wywołanie WorkContinuation.then(...) zwraca nową instancję WorkContinuation. Jeśli dodasz List z OneTimeWorkRequest instancji, te żądania mogą być wykonywane równolegle.
Na koniec możesz użyć metody WorkContinuation.enqueue(), aby enqueue() łańcuch WorkContinuation.
Przeanalizujmy przykład. W tym przykładzie skonfigurowano 3 różne zadania instancji roboczej (które mogą być uruchamiane równolegle). Wyniki tych instancji roboczych są następnie łączone i przekazywane do zadania instancji roboczej buforowania. Na koniec dane wyjściowe tego zadania są przekazywane do instancji roboczej przesyłania, która przesyła wyniki na serwer zdalny.
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();
Łączenie danych wejściowych
Gdy połączysz instancje OneTimeWorkRequest, dane wyjściowe nadrzędnych żądań roboczych zostaną przekazane jako dane wejściowe do podrzędnych. W przykładzie powyżej dane wyjściowe z plantName1, plantName2 i plantName3 zostaną przekazane jako dane wejściowe do żądania cache.
Do zarządzania danymi wejściowymi z wielu nadrzędnych żądań WorkRequest WorkManager używa klasy InputMerger.
WorkManager udostępnia 2 rodzaje InputMerger:
OverwritingInputMergerpróbuje dodać wszystkie klucze ze wszystkich danych wejściowych do danych wyjściowych. W przypadku konfliktów zastępuje wcześniej ustawione klucze.ArrayCreatingInputMergerpróbuje scalić dane wejściowe, tworząc w razie potrzeby tablice.
Jeśli masz bardziej konkretny 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 wynikowych danych wyjściowych.
Jeśli na przykład dane wejściowe fabryki mają klucz pasujący do odpowiednich nazw zmiennych ("plantName1", "plantName2" i "plantName3"), dane przekazywane do instancji roboczej cache będą miały 3 pary klucz-wartość.
Jeśli wystąpi konflikt, „wygrywa” ostatni pracownik, który zakończył pracę, a jego wartość jest przekazywana do cache.
Żądania robocze są uruchamiane równolegle, więc nie ma gwarancji, że będą wykonywane w określonej kolejności. W przykładzie powyżej zmienna plantName1 może mieć 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 w scalaniu, lepszym rozwiązaniem może być ArrayCreatingInputMerger.
ArrayCreatingInputMerger
W powyższym przykładzie, ponieważ chcemy zachować dane wyjściowe ze wszystkich instancji roboczych nazwy rośliny, 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 paruje każdy klucz z tablicą. Jeśli każdy z kluczy jest unikalny, wynikiem jest seria tablic jednoelementowych.
Jeśli wystąpią kolizje kluczy, odpowiednie wartości zostaną zgrupowane w tablicy.
Łączenie i stany pracy
Łańcuchy OneTimeWorkRequest są wykonywane sekwencyjnie, o ile ich zadania kończą się powodzeniem (czyli zwracają Result.success()). Żądania zadań mogą się nie powieść lub zostać anulowane podczas działania, co ma wpływ na zależne żądania zadań.
Gdy pierwsze żądanie OneTimeWorkRequest zostanie dodane do kolejki w łańcuchu żądań, wszystkie kolejne żądania będą blokowane do czasu zakończenia pierwszego żądania.
Po dodaniu do kolejki i spełnieniu wszystkich ograniczeń dotyczących zadania pierwsze żądanie zadania zaczyna się wykonywać. Jeśli zadanie zostanie pomyślnie ukończone w głównym elemencie OneTimeWorkRequest lub List<OneTimeWorkRequest> (czyli zwróci Result.success()), do kolejki zostanie dodany następny zestaw zależnych żądań zadania.
Jeśli każde żądanie zostanie zrealizowane, ten sam wzorzec będzie propagowany w pozostałej części łańcucha żądań, aż wszystkie zadania w łańcuchu zostaną ukończone. Jest to najprostszy i często preferowany przypadek, ale stany błędów są równie ważne.
Jeśli podczas przetwarzania żądania przez instancję roboczą wystąpi błąd, możesz ponowić żądanie zgodnie ze zdefiniowaną przez siebie zasadą wycofywania. Ponowienie żądania, które jest częścią łańcucha, oznacza, że tylko to żądanie zostanie ponowione z podanymi danymi wejściowymi. Nie będzie to miało wpływu na zadania wykonywane równolegle.
Więcej informacji o definiowaniu niestandardowych strategii ponawiania znajdziesz w artykule Zasady ponawiania i wycofywania.
Jeśli zasada ponawiania jest niezdefiniowana lub wyczerpana albo w inny sposób osiągniesz stan, w którym OneTimeWorkRequest zwraca Result.failure(), to żądanie i wszystkie zależne od niego żądania zostaną oznaczone jako FAILED.
Ta sama logika obowiązuje w przypadku anulowania OneTimeWorkRequest. Wszystkie zależne żądania robocze również są oznaczone jako CANCELLED, a ich zadania nie zostaną wykonane.
Pamiętaj, że jeśli dołączysz więcej żądań do łańcucha, który zawiera nieudane lub anulowane żądania, nowo dołączone żądanie również zostanie oznaczone odpowiednio jako FAILED lub CANCELLED. Jeśli chcesz rozszerzyć działanie istniejącego łańcucha, zapoznaj się z APPEND_OR_REPLACE w ExistingWorkPolicy.
Podczas tworzenia łańcuchów żądań pracy zależne żądania pracy powinny definiować zasady ponawiania, aby zapewnić, że praca zawsze zostanie wykonana na czas. Nieudane żądania robocze mogą skutkować niekompletnymi łańcuchami lub nieoczekiwanym stanem.
Więcej informacji znajdziesz w artykule o anulowaniu i zatrzymywaniu zadań.