Aufgaben verketten

Mit WorkManager können Sie eine Kette von Arbeitsvorgängen erstellen und in die Warteschlange stellen, in der mehrere abhängige Aufgaben angegeben werden und die Reihenfolge definiert wird, in der sie ausgeführt werden sollen. Diese Funktion ist besonders nützlich, wenn Sie mehrere Aufgaben in einer bestimmten Reihenfolge ausführen müssen.

Um eine Kette von Aufgaben zu erstellen, können Sie WorkManager.beginWith(OneTimeWorkRequest) oder WorkManager.beginWith(List<OneTimeWorkRequest>) verwenden, die jeweils eine Instanz von WorkContinuation zurückgeben.

Mit einem WorkContinuation können dann abhängige OneTimeWorkRequest-Instanzen mit then(OneTimeWorkRequest) oder then(List<OneTimeWorkRequest>) hinzugefügt werden.

Bei jedem Aufruf von WorkContinuation.then(...) wird eine neue Instanz von WorkContinuation zurückgegeben. Wenn Sie List mit OneTimeWorkRequest Instanzen hinzufügen, können diese Anfragen möglicherweise parallel ausgeführt werden.

Schließlich können Sie die Methode WorkContinuation.enqueue() verwenden, um die Kette von WorkContinuations zu enqueue().

Sehen wir uns ein Beispiel an. In diesem Beispiel sind drei verschiedene Worker-Jobs konfiguriert, die (potenziell parallel) ausgeführt werden. Die Ergebnisse dieser Worker werden dann zusammengeführt und an einen Caching-Worker-Job übergeben. Schließlich wird die Ausgabe dieses Jobs an einen Upload-Worker übergeben, der die Ergebnisse auf einen Remote-Server hochlädt.

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();

Input Mergers

Wenn Sie OneTimeWorkRequest-Instanzen verketten, wird die Ausgabe übergeordneter Arbeitsanfragen als Eingabe an die untergeordneten Anfragen übergeben. Im obigen Beispiel werden die Ausgaben von plantName1, plantName2 und plantName3 als Eingaben für die cache-Anfrage übergeben.

WorkManager verwendet InputMerger, um Eingaben aus mehreren übergeordneten Arbeitsanfragen zu verwalten.

WorkManager bietet zwei verschiedene Arten von InputMerger:

  • OverwritingInputMerger versucht, alle Schlüssel aus allen Eingaben in die Ausgabe aufzunehmen. Bei Konflikten werden die zuvor festgelegten Schlüssel überschrieben.

  • ArrayCreatingInputMerger versucht, die Eingaben zusammenzuführen und bei Bedarf Arrays zu erstellen.

Wenn Sie einen spezifischeren Anwendungsfall haben, können Sie Ihre eigene Klasse durch Unterklassenbildung von InputMerger schreiben.

OverwritingInputMerger

OverwritingInputMerger ist die Standardmethode zum Zusammenführen. Wenn es beim Zusammenführen zu Schlüsselkonflikten kommt, wird der letzte Wert für einen Schlüssel alle vorherigen Versionen in den resultierenden Ausgabedaten überschreiben.

Wenn die Anlagen-Eingaben beispielsweise jeweils einen Schlüssel haben, der mit den entsprechenden Variablennamen übereinstimmt ("plantName1", "plantName2" und "plantName3"), enthalten die an den cache-Worker übergebenen Daten drei Schlüssel/Wert-Paare.

Diagramm mit drei Jobs, die unterschiedliche Ausgaben an den nächsten Job in der Kette übergeben. Da die drei Ausgaben alle unterschiedliche Schlüssel haben, erhält der nächste Job drei Schlüssel/Wert-Paare.

Bei einem Konflikt „gewinnt“ der letzte Worker, der die Aufgabe abgeschlossen hat, und sein Wert wird an cache übergeben.

Diagramm mit drei Jobs, die Ausgaben an den nächsten Job in der Kette übergeben. In diesem Fall erzeugen zwei dieser Jobs Ausgaben mit demselben Schlüssel. Daher erhält der nächste Job zwei Schlüssel/Wert-Paare, wobei eine der in Konflikt stehenden Ausgaben verworfen wird.

Da Ihre Arbeitsanfragen parallel ausgeführt werden, gibt es keine Garantie für die Reihenfolge, in der sie ausgeführt werden. Im obigen Beispiel kann plantName1 entweder den Wert "tulip" oder "elm" enthalten, je nachdem, welcher Wert zuletzt geschrieben wurde. Wenn die Wahrscheinlichkeit eines Schlüsselkonflikts besteht und Sie alle Ausgabedaten bei einem Merge beibehalten müssen, ist ArrayCreatingInputMerger möglicherweise die bessere Option.

ArrayCreatingInputMerger

Im obigen Beispiel möchten wir die Ausgaben aller Worker mit dem Namen „plant“ beibehalten. Daher sollten wir ArrayCreatingInputMerger verwenden.

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();

Mit ArrayCreatingInputMerger wird jedem Schlüssel ein Array zugeordnet. Wenn jeder der Schlüssel eindeutig ist, besteht das Ergebnis aus einer Reihe von Arrays mit einem Element.

Diagramm mit drei Jobs, die unterschiedliche Ausgaben an den nächsten Job in der Kette übergeben. An den nächsten Job werden drei Arrays übergeben, eines für jeden der Ausgabeschlüssel. Jedes Array hat ein einzelnes Element.

Bei Schlüsselkollisionen werden alle entsprechenden Werte in einem Array zusammengefasst.

Diagramm mit drei Jobs, die Ausgaben an den nächsten Job in der Kette übergeben. In diesem Fall erzeugen zwei dieser Jobs Ausgaben mit demselben Schlüssel. An den nächsten Job werden zwei Arrays übergeben, eines für jeden Schlüssel. Eines dieser Arrays hat zwei Elemente, da es zwei Ausgaben mit diesem Schlüssel gab.

Verkettung und Arbeitsstatus

Ketten von OneTimeWorkRequest werden sequenziell ausgeführt, solange ihre Arbeit erfolgreich abgeschlossen wird (d. h., sie geben ein Result.success() zurück). Arbeitsanfragen können während der Ausführung fehlschlagen oder abgebrochen werden, was sich auf abhängige Arbeitsanfragen auswirkt.

Wenn die erste OneTimeWorkRequest in eine Kette von Arbeitsanfragen eingereiht wird, werden alle nachfolgenden Arbeitsanfragen blockiert, bis die Arbeit dieser ersten Arbeitsanfrage abgeschlossen ist.

Diagramm mit einer Kette von Jobs. Der erste Job wird in die Warteschlange gestellt. Alle nachfolgenden Jobs werden blockiert, bis der erste abgeschlossen ist.

Sobald die Anfrage in die Warteschlange gestellt wurde und alle Arbeitsbedingungen erfüllt sind, wird die erste Arbeitsanfrage ausgeführt. Wenn die Arbeit im Stammverzeichnis OneTimeWorkRequest oder List<OneTimeWorkRequest> erfolgreich abgeschlossen wird (d. h., es wird ein Result.success() zurückgegeben), wird die nächste Gruppe abhängiger Arbeitsanfragen in die Warteschlange gestellt.

Diagramm mit einer Kette von Jobs. Der erste Job wurde erfolgreich abgeschlossen und seine beiden direkten Nachfolger werden in die Warteschlange eingereiht. Die verbleibenden Jobs werden blockiert, bis die vorherigen Jobs abgeschlossen sind.

Solange jede Arbeitsanfrage erfolgreich abgeschlossen wird, setzt sich dieses Muster durch den Rest Ihrer Kette von Arbeitsanfragen fort, bis alle Arbeiten in der Kette abgeschlossen sind. Das ist zwar der einfachste und oft bevorzugte Fall, aber Fehlerzustände sind genauso wichtig.

Wenn bei der Verarbeitung Ihrer Arbeitsanfrage durch einen Worker ein Fehler auftritt, können Sie die Anfrage gemäß einer von Ihnen definierten Backoff-Richtlinie noch einmal versuchen. Wenn Sie eine Anfrage, die Teil einer Kette ist, noch einmal versuchen, wird nur diese Anfrage mit den ihr zur Verfügung gestellten Eingabedaten wiederholt. Parallel ausgeführte Vorgänge sind davon nicht betroffen.

Diagramm mit einer Kette von Jobs. Einer der Jobs ist fehlgeschlagen, aber es war eine Backoff-Richtlinie definiert. Dieser Job wird nach Ablauf der entsprechenden Zeit noch einmal ausgeführt. Die nachfolgenden Jobs in der Kette werden blockiert, bis er erfolgreich ausgeführt wird.

Weitere Informationen zum Definieren benutzerdefinierter Wiederholungsstrategien finden Sie unter Retry and Backoff Policy.

Wenn diese Richtlinie für Wiederholungsversuche nicht definiert oder erschöpft ist oder Sie anderweitig einen Zustand erreichen, in dem ein OneTimeWorkRequest Result.failure() zurückgibt, werden diese Arbeitsanfrage und alle abhängigen Arbeitsanfragen als FAILED. markiert.

Diagramm mit einer Kette von Jobs. Ein Job ist fehlgeschlagen und kann nicht wiederholt werden. Daher schlagen auch alle nachfolgenden Jobs in der Kette fehl.

Dieselbe Logik gilt, wenn ein OneTimeWorkRequest gekündigt wird. Alle Anfragen für abhängige Aufgaben werden ebenfalls mit CANCELLED gekennzeichnet und die Aufgaben werden nicht ausgeführt.

Diagramm mit einer Kette von Jobs. Ein Job wurde abgebrochen. Daher werden auch alle Jobs danach in der Kette abgebrochen.

Wenn Sie einer Kette, bei der Arbeitsanfragen fehlgeschlagen oder abgebrochen wurden, weitere Arbeitsanfragen hinzufügen, werden diese ebenfalls mit FAILED bzw. CANCELLED gekennzeichnet. Wenn Sie die Arbeit einer vorhandenen Kette erweitern möchten, sehen Sie sich APPEND_OR_REPLACE in ExistingWorkPolicy an.

Wenn Sie Ketten von Arbeitsanfragen erstellen, sollten für abhängige Arbeitsanfragen Richtlinien für Wiederholungsversuche definiert werden, damit die Arbeit immer rechtzeitig abgeschlossen wird. Fehlgeschlagene Arbeitsanfragen können zu unvollständigen Ketten und/oder einem unerwarteten Status führen.

Weitere Informationen finden Sie unter Arbeit abbrechen und beenden.