Aufgaben verketten

Mit WorkManager können Sie eine Kette von Aufgaben erstellen und in die Warteschlange stellen, die mehrere abhängige Aufgaben angibt und die Reihenfolge definiert, 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.

Wenn Sie eine Arbeitskette erstellen möchten, können Sie WorkManager.beginWith(OneTimeWorkRequest) oder WorkManager.beginWith(List<OneTimeWorkRequest>) verwenden. Beide geben eine Instanz von WorkContinuation zurück.

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 einen List von OneTimeWorkRequest Instanzen hinzufügen, können diese Anfragen potenziell parallel ausgeführt werden.

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

Sehen wir uns ein Beispiel an. In diesem Beispiel sind drei verschiedene Worker-Jobs so konfiguriert, dass sie (potenziell parallel) ausgeführt werden. Die Ergebnisse dieser Worker werden dann zusammengeführt und an einen Caching-Worker-Job weitergegeben. 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();

Eingabefusionen

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

Zur Verwaltung von Eingaben aus mehreren übergeordneten Arbeitsanfragen verwendet WorkManager InputMerger.

WorkManager bietet zwei verschiedene Arten von InputMerger:

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

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

Wenn Sie einen spezifischeren Anwendungsfall haben, können Sie eine eigene Klasse schreiben, indem Sie eine Unterklasse von InputMerger erstellen.

OverwritingInputMerger

OverwritingInputMerger ist die Standardmethode für die Zusammenführung. Wenn es bei der Zusammenführung zu Schlüsselkonflikten kommt, überschreibt der neueste Wert für einen Schlüssel alle vorherigen Versionen in den resultierenden Ausgabedaten.

Wenn die Eingaben für die Anlage beispielsweise jeweils einen Schlüssel haben, der mit den entsprechenden Variablennamen ("plantName1", "plantName2" und "plantName3") übereinstimmt, 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, empfängt der nächste Job drei Schlüssel/Wert-Paare.

Wenn ein Konflikt auftritt, „gewinnt“ der Worker, der zuletzt fertig ist, und sein Wert wird an cache übergeben.

Diagramm, das drei Jobs zeigt, die Ausgaben an den nächsten Job in der Kette übergeben. In diesem Fall erzeugen zwei dieser Jobs Ausgaben mit demselben Schlüssel. Der nächste Job erhält dann 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 könnte plantName1 entweder den Wert "tulip" oder "elm" enthalten, je nachdem, welcher Wert zuletzt geschrieben wurde. Wenn die Möglichkeit eines Schlüsselkonflikts besteht und Sie alle Ausgabedaten in einer Zusammenführung beibehalten müssen, ist ArrayCreatingInputMerger möglicherweise die bessere Option.

ArrayCreatingInputMerger

Im obigen Beispiel möchten wir die Ausgaben aller Worker für Pflanzennamen beibehalten. Daher sollten wir einen 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();

ArrayCreatingInputMerger ordnet jedem Schlüssel ein Array zu. Wenn jeder Schlüssel eindeutig ist, ist das Ergebnis eine 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 Ausgabeschlüssel. Jedes Array hat ein einzelnes Mitglied.

Wenn Schlüsselkonflikte auftreten, werden alle entsprechenden Werte in einem Array gruppiert.

Diagramm, das drei Jobs zeigt, 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 Mitglieder, da es zwei Ausgaben mit diesem Schlüssel gab.

Verkettung und Arbeitsstatus

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

Wenn die erste OneTimeWorkRequest in einer Kette von Arbeitsanfragen in die Warteschlange gestellt wird, werden alle nachfolgenden Arbeitsanfragen blockiert, bis die Arbeit der ersten Arbeitsanfrage abgeschlossen ist.

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

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

Diagramm, das eine Kette von Jobs zeigt. Der erste Job war erfolgreich und die beiden unmittelbaren Nachfolger wurden in die Warteschlange gestellt. Die verbleibenden Jobs werden blockiert, bis die vorherigen Jobs abgeschlossen sind.

Solange jede Arbeitsanfrage erfolgreich abgeschlossen wird, wird dieses Muster auf die restlichen Arbeitsanfragen in der Kette angewendet, bis alle Arbeiten in der Kette abgeschlossen sind. Das ist zwar der einfachste und oft bevorzugte Fall, aber Fehlerstatus 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 wiederholen. Wenn Sie eine Anfrage wiederholen, die Teil einer Kette ist, wird nur diese Anfrage mit den dafür bereitgestellten Eingabedaten wiederholt. Parallel ausgeführte Arbeiten sind davon nicht betroffen.

Diagramm, das eine Kette von Jobs zeigt. Einer der Jobs ist fehlgeschlagen, aber es wurde eine Backoff-Richtlinie definiert. Der Job wird nach Ablauf der entsprechenden Zeit noch einmal ausgeführt. Die nachfolgenden Jobs in der Kette werden blockiert, bis der Job erfolgreich ausgeführt wurde.

Weitere Informationen zum Definieren benutzerdefinierter Wiederholungsstrategien finden Sie unter Wiederholungs- und Backoff-Richtlinie.

Wenn diese Wiederholungsrichtlinie nicht definiert oder ausgeschö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, das eine Kette von Jobs zeigt. 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 abgebrochen wird. Alle abhängigen Arbeitsanfragen werden ebenfalls mit CANCELLED gekennzeichnet und die zugehörigen Aufgaben werden nicht ausgeführt.

Diagramm, das eine Kette von Jobs zeigt. Ein Job wurde abgebrochen. Daher werden auch alle nachfolgenden Jobs in der Kette abgebrochen.

Wenn Sie weitere Arbeitsanfragen an eine Kette anhängen, die fehlgeschlagene oder abgebrochene Arbeitsanfragen enthält, wird die neu angehängte Arbeitsanfrage ebenfalls als FAILED bzw. CANCELLED markiert. Wenn Sie die Arbeit einer vorhandenen Kette erweitern möchten, finden Sie weitere Informationen unter APPEND_OR_REPLACE in ExistingWorkPolicy.

Beim Erstellen von Ketten von Arbeitsanfragen sollten für abhängige Arbeitsanfragen Wiederholungsrichtlinien definiert werden, damit die Arbeit immer rechtzeitig abgeschlossen wird. Fehlgeschlagene Arbeitsanfragen können zu unvollständigen Ketten und/oder unerwarteten Zuständen führen.

Weitere Informationen finden Sie unter Arbeit abbrechen und beenden.