Nachdem Sie Worker
und WorkRequest
definiert haben, besteht der letzte Schritt darin, Ihre Arbeit in die Warteschlange zu stellen. Am einfachsten können Sie die Arbeit in die Warteschlange stellen, indem Sie die WorkManager-Methode enqueue()
aufrufen und die WorkRequest
übergeben, die Sie ausführen möchten.
Kotlin
val myWork: WorkRequest = // ... OneTime or PeriodicWork WorkManager.getInstance(requireContext()).enqueue(myWork)
Java
WorkRequest myWork = // ... OneTime or PeriodicWork WorkManager.getInstance(requireContext()).enqueue(myWork);
Achten Sie darauf, Aufgaben in die Warteschlange zu stellen, um Duplikate zu vermeiden. Beispielsweise kann eine Anwendung versuchen, ihre Logs alle 24 Stunden auf einen Back-End-Dienst hochzuladen. Wenn Sie nicht aufpassen, stellen Sie dieselbe Aufgabe unter Umständen mehrmals in die Warteschlange, obwohl der Job nur einmal ausgeführt werden muss. Zu diesem Zweck können Sie die Arbeit als einzigartige Arbeit planen.
Einzigartige Arbeit
Einzigartige Arbeit ist ein leistungsstarkes Konzept, das garantiert, dass Sie jeweils nur eine Arbeitsinstanz mit einem bestimmten Namen haben. Im Gegensatz zu IDs sind eindeutige Namen für Menschen lesbar und werden vom Entwickler angegeben und nicht automatisch von WorkManager generiert. Im Gegensatz zu Tags werden eindeutige Namen nur einer einzelnen Arbeitsinstanz zugeordnet.
Einzigartige Arbeiten können sowohl bei einmaligen als auch bei regelmäßigen Arbeiten angewandt werden. Sie können einen eindeutigen Ablauf erstellen, indem Sie eine dieser Methoden aufrufen, je nachdem, ob Sie wiederkehrende oder einmalige Arbeiten planen.
WorkManager.enqueueUniqueWork()
für einmalige ArbeitWorkManager.enqueueUniquePeriodicWork()
für regelmäßige Arbeiten
Beide Methoden akzeptieren drei Argumente:
- uniqueWorkName: Ein
String
, der zur eindeutigen Identifizierung der Arbeitsanfrage verwendet wird. - existingWorkPolicy: Ein
enum
, das WorkManager mitteilt, was zu tun ist, wenn es bereits eine unvollendete Arbeitskette mit diesem eindeutigen Namen gibt. Weitere Informationen finden Sie in der Richtlinie zur Konfliktlösung. - work: der zu planende Wert (
WorkRequest
).
Mit eigenen Arbeiten können wir das zuvor erwähnte Problem mit doppelten Terminbuchungen beheben.
Kotlin
val sendLogsWorkRequest = PeriodicWorkRequestBuilder<SendLogsWorker>(24, TimeUnit.HOURS) .setConstraints(Constraints.Builder() .setRequiresCharging(true) .build() ) .build() WorkManager.getInstance(this).enqueueUniquePeriodicWork( "sendLogs", ExistingPeriodicWorkPolicy.KEEP, sendLogsWorkRequest )
Java
PeriodicWorkRequest sendLogsWorkRequest = new PeriodicWorkRequest.Builder(SendLogsWorker.class, 24, TimeUnit.HOURS) .setConstraints(new Constraints.Builder() .setRequiresCharging(true) .build() ) .build(); WorkManager.getInstance(this).enqueueUniquePeriodicWork( "sendLogs", ExistingPeriodicWorkPolicy.KEEP, sendLogsWorkRequest);
Wenn der Code jetzt ausgeführt wird, während sich bereits ein sendLogs-Job in der Warteschlange befindet, wird der vorhandene Job beibehalten und es wird kein neuer Job hinzugefügt.
Eindeutige Arbeitssequenzen können auch nützlich sein, wenn Sie eine lange Kette von Aufgaben schrittweise aufbauen müssen. In einer Bildbearbeitungs-App können Nutzer beispielsweise eine lange Reihe von Aktionen rückgängig machen. Jeder dieser Schritte zum Rückgängigmachen kann eine Weile dauern, muss aber in der richtigen Reihenfolge ausgeführt werden. In diesem Fall könnte die Anwendung eine Kette vom Typ "Rückgängig machen" erstellen und jeden Vorgang zum Rückgängigmachen nach Bedarf an die Kette anhängen. Weitere Informationen finden Sie unter Kettenarbeiten.
Richtlinie zur Konfliktlösung
Beim Planen einmaliger Arbeiten müssen Sie WorkManager mitteilen, welche Aktion bei einem Konflikt ausgeführt werden soll. Dazu übergeben Sie beim Einreihen der Arbeit eine enum.
Für einmalige Arbeiten stellen Sie eine ExistingWorkPolicy
bereit, die vier Optionen für die Verarbeitung des Konflikts unterstützt.
REPLACE
vorhandene Arbeit mit der neuen Arbeit. Mit dieser Option wird die vorhandene Arbeit abgebrochen.KEEP
vorhandene Arbeit und ignorieren die neue.APPEND
die neue Arbeit an das Ende der vorhandenen Arbeit an. Durch diese Richtlinie wird Ihre neue Arbeit an die vorhandene Arbeit verkettet und nach Abschluss der vorhandenen Arbeit ausgeführt.
Die vorhandene Arbeit wird zu einer Voraussetzung für das neue Werk. Wenn das vorhandene Werk zu CANCELLED
oder FAILED
wird, ist das neue Werk ebenfalls CANCELLED
oder FAILED
.
Wenn die neue Arbeit unabhängig vom Status der vorhandenen Arbeit ausgeführt werden soll, verwenden Sie stattdessen APPEND_OR_REPLACE
.
APPEND_OR_REPLACE
funktioniert ähnlich wieAPPEND
, mit der Ausnahme, dass es nicht vom erforderlichen Arbeitsstatus abhängt. Wenn die vorhandene ArbeitCANCELLED
oderFAILED
ist, wird sie trotzdem ausgeführt.
Für Arbeiten in der Periode stellst du ein ExistingPeriodicWorkPolicy
bereit, das zwei Optionen unterstützt: REPLACE
und KEEP
. Diese Optionen funktionieren genauso wie die „existingWorkPolicy“-Entsprechungen.
Ihre Arbeit beobachten
Nachdem die Arbeit in die Warteschlange gestellt wurde, können Sie ihren Status jederzeit prüfen, indem Sie WorkManager über die zugehörige name
, id
oder eine verknüpfte tag
abfragen.
Kotlin
// by id workManager.getWorkInfoById(syncWorker.id) // ListenableFuture<WorkInfo> // by name workManager.getWorkInfosForUniqueWork("sync") // ListenableFuture<List<WorkInfo>> // by tag workManager.getWorkInfosByTag("syncTag") // ListenableFuture<List<WorkInfo>>
Java
// by id workManager.getWorkInfoById(syncWorker.id); // ListenableFuture<WorkInfo> // by name workManager.getWorkInfosForUniqueWork("sync"); // ListenableFuture<List<WorkInfo>> // by tag workManager.getWorkInfosByTag("syncTag"); // ListenableFuture<List<WorkInfo>>
Die Abfrage gibt ein ListenableFuture
eines WorkInfo
-Objekts zurück, das den id
des Werks, dessen Tags, den aktuellen State
und jeden Ausgabedatensatz über Result.success(outputData)
enthält.
Mit einer LiveData
-Variante jeder der Methoden können Sie Änderungen am WorkInfo
beobachten, indem Sie einen Listener registrieren. Wenn Sie beispielsweise dem Nutzer eine Nachricht anzeigen möchten, wenn einige Vorgänge erfolgreich abgeschlossen wurden, können Sie diese so einrichten:
Kotlin
workManager.getWorkInfoByIdLiveData(syncWorker.id) .observe(viewLifecycleOwner) { workInfo -> if(workInfo?.state == WorkInfo.State.SUCCEEDED) { Snackbar.make(requireView(), R.string.work_completed, Snackbar.LENGTH_SHORT) .show() } }
Java
workManager.getWorkInfoByIdLiveData(syncWorker.id) .observe(getViewLifecycleOwner(), workInfo -> { if (workInfo.getState() != null && workInfo.getState() == WorkInfo.State.SUCCEEDED) { Snackbar.make(requireView(), R.string.work_completed, Snackbar.LENGTH_SHORT) .show(); } });
Komplexe Arbeitsabfragen
WorkManager 2.4.0 und höher unterstützt komplexe Abfragen für Jobs in der Warteschlange mit WorkQuery
-Objekten. WorkQuery unterstützt die Abfrage von Aufgaben anhand einer Kombination aus Tags, Status und eindeutigem Arbeitsnamen.
Das folgende Beispiel zeigt, wie Sie alle Arbeiten mit dem Tag "syncTag" finden, das sich im Status FAILED
oder CANCELLED
befindet und einen eindeutigen Arbeitsnamen entweder "preProcess" oder "sync" hat.
Kotlin
val workQuery = WorkQuery.Builder .fromTags(listOf("syncTag")) .addStates(listOf(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)) .addUniqueWorkNames(listOf("preProcess", "sync") ) .build() val workInfos: ListenableFuture<List<WorkInfo>> = workManager.getWorkInfos(workQuery)
Java
WorkQuery workQuery = WorkQuery.Builder .fromTags(Arrays.asList("syncTag")) .addStates(Arrays.asList(WorkInfo.State.FAILED, WorkInfo.State.CANCELLED)) .addUniqueWorkNames(Arrays.asList("preProcess", "sync") ) .build(); ListenableFuture<List<WorkInfo>> workInfos = workManager.getWorkInfos(workQuery);
Jede Komponente (Tag, Status oder Name) in einem WorkQuery
ist AND
-verknüpft mit den anderen. Jeder Wert in einer Komponente ist OR
-eddig. Beispiel: (name1 OR name2
OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...)
.
WorkQuery
funktioniert auch mit dem LiveData-Äquivalent getWorkInfosLiveData()
.
Arbeit abbrechen und beenden
Wenn Sie Ihre in die Warteschlange eingereihte Arbeit nicht mehr benötigen, können Sie deren Abbruch anfordern. Arbeit kann durch name
, id
oder eine damit verknüpfte tag
abgebrochen werden.
Kotlin
// by id workManager.cancelWorkById(syncWorker.id) // by name workManager.cancelUniqueWork("sync") // by tag workManager.cancelAllWorkByTag("syncTag")
Java
// by id workManager.cancelWorkById(syncWorker.id); // by name workManager.cancelUniqueWork("sync"); // by tag workManager.cancelAllWorkByTag("syncTag");
Intern prüft WorkManager die State
der Arbeit. Wenn die Arbeit bereits fertig ist, passiert nichts. Andernfalls wird der Status der Arbeit in CANCELLED
geändert und die Arbeit wird in der Zukunft nicht ausgeführt. Alle WorkRequest
-Jobs, die von dieser Arbeit abhängig sind, sind ebenfalls CANCELLED
.
Derzeit erhält RUNNING
einen Aufruf an ListenableWorker.onStopped()
.
Überschreiben Sie diese Methode, um eine mögliche Bereinigung abzuwickeln. Weitere Informationen finden Sie unter Ausführen von Workern beenden.
Ausführenden Worker anhalten
Das Ausführen von Worker
kann aus verschiedenen Gründen von WorkManager angehalten werden:
- Sie haben die Stornierung explizit angefordert (z. B. durch Aufrufen von
WorkManager.cancelWorkById(UUID)
). - Im Fall von eindeutigen Arbeiten haben Sie explizit eine neue
WorkRequest
mit einemExistingWorkPolicy
vonREPLACE
in die Warteschlange gestellt. Das alteWorkRequest
gilt sofort als storniert. - Die Einschränkungen Ihrer Arbeit werden nicht mehr erfüllt.
- Das System hat deine App angewiesen, deine Arbeit aus irgendeinem Grund zu beenden. Dies kann passieren, wenn Sie die Ausführungsfrist von 10 Minuten überschreiten. Die Arbeit wird für eine spätere Wiederholung geplant.
Unter diesen Bedingungen wird Ihr Worker angehalten.
Sie sollten alle laufenden Arbeiten gemeinsam abbrechen und alle Ressourcen freigeben, an denen der Worker sich hält. Zum Beispiel sollten Sie an dieser Stelle offene Handles für Datenbanken und Dateien schließen. Ihnen stehen zwei Mechanismen zur Verfügung, um herauszufinden, wann Ihr Worker angehalten wird.
onStopped()-Callback
WorkManager ruft ListenableWorker.onStopped()
auf, sobald der Worker angehalten wurde. Überschreiben Sie diese Methode, um alle Ressourcen zu schließen, an denen Sie möglicherweise festhalten.
Eigenschaft "isStopped()"
Sie können die Methode ListenableWorker.isStopped()
aufrufen, um zu prüfen, ob der Worker bereits angehalten wurde. Wenn Sie lang andauernde oder sich wiederholende Vorgänge in Ihrem Worker ausführen, sollten Sie dieses Attribut regelmäßig überprüfen und es als Signal dafür verwenden, die Arbeit so schnell wie möglich zu beenden.
Hinweis:WorkManager ignoriert die Result
, die von einem Worker festgelegt wurde, der das onStop-Signal erhalten hat, da der Worker bereits als beendet gilt.