Nachdem Sie Ihre
Worker und
Ihre WorkRequest definiert haben,
besteht der letzte Schritt darin, die Arbeit in die Warteschlange zu stellen. Die einfachste Möglichkeit, Arbeit in die Warteschlange zu stellen, ist der Aufruf der enqueue()-Methode von WorkManager und die Übergabe des auszuführenden WorkRequest.
Kotlin
val myWork: WorkRequest = // ... OneTime or PeriodicWork
WorkManager.getInstance(requireContext()).enqueue(myWork)
Java
WorkRequest myWork = // ... OneTime or PeriodicWork
WorkManager.getInstance(requireContext()).enqueue(myWork);
Seien Sie vorsichtig, wenn Sie Arbeit in die Warteschlange stellen, um Duplizierungen zu vermeiden. Eine App kann beispielsweise versuchen, ihre Logs alle 24 Stunden in einen Backend-Dienst hochzuladen. Wenn Sie nicht aufpassen, stellen Sie die gleiche Aufgabe möglicherweise mehrmals in die Warteschlange, obwohl der Job nur einmal ausgeführt werden muss. Um dies zu erreichen, können Sie die Arbeit als eindeutige Arbeit planen.
Eindeutige Arbeit
Eindeutige 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 menschenlesbar und werden vom Entwickler angegeben, anstatt automatisch von WorkManager generiert zu werden. Im Gegensatz zu Tags sind eindeutige Namen nur einer einzelnen Arbeitsinstanz zugeordnet.
Eindeutige Arbeit kann sowohl auf einmalige als auch auf periodische Arbeit angewendet werden. Sie können eine eindeutige Arbeitssequenz erstellen, indem Sie eine dieser Methoden aufrufen, je nachdem, ob Sie wiederholte oder einmalige Arbeit planen.
WorkManager.enqueueUniqueWork()für einmalige ArbeitWorkManager.enqueueUniquePeriodicWork()für periodische Arbeit
Beide Methoden akzeptieren drei Argumente:
- uniqueWorkName – Ein
String, mit dem die Arbeits anfrage eindeutig identifiziert wird. - existingWorkPolicy – Ein
enum, das WorkManager anweist, was zu tun ist , wenn bereits eine unvollständige Arbeitskette mit diesem eindeutigen Namen vorhanden ist. Weitere Informationen finden Sie unter Richtlinie zur Konfliktlösung. - work – das zu planende
WorkRequest.
Mit eindeutiger Arbeit können wir das Problem mit der doppelten Planung beheben, das wir zuvor festgestellt haben.
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 kein neuer Job hinzugefügt.
Eindeutige Arbeitssequenzen können auch nützlich sein, wenn Sie eine lange Kette von Aufgaben schrittweise aufbauen müssen. Mit einer Fotobearbeitungs-App können Nutzer beispielsweise eine lange Kette von Aktionen rückgängig machen. Jeder dieser Rückgängig-Vorgänge kann einige Zeit dauern, muss aber in der richtigen Reihenfolge ausgeführt werden. In diesem Fall könnte die App eine „Rückgängig“-Kette erstellen und bei Bedarf jeden Rückgängig-Vorgang an die Kette anhängen. Weitere Informationen finden Sie unter Arbeit verketten.
Richtlinie zur Konfliktlösung
Wenn Sie eindeutige Arbeit planen, müssen Sie WorkManager mitteilen, welche Aktion bei einem Konflikt ausgeführt werden soll. Dazu übergeben Sie beim Einreihen der Arbeit in die Warteschlange ein Enum.
Für einmalige Arbeit geben Sie ein
ExistingWorkPolicy an, das
vier Optionen für die Behandlung des Konflikts unterstützt.
REPLACE: Ersetzt die vorhandene Arbeit durch die neue Arbeit. Mit dieser Option wird die vorhandene Arbeit abgebrochen.KEEP: Behält die vorhandene Arbeit bei und ignoriert die neue Arbeit.APPEND: Fügt die neue Arbeit am Ende der vorhandenen Arbeit an. Mit dieser Richtlinie wird die neue Arbeit an die vorhandene Arbeit angehängt und nach Abschluss der vorhandenen Arbeit ausgeführt.
Die vorhandene Arbeit wird zu einer Voraussetzung für die neue Arbeit. Wenn die vorhandene Arbeit CANCELLED oder FAILED ist, ist auch die neue Arbeit 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_REPLACEfunktioniert ähnlich wieAPPEND, ist aber nicht vom Status der Voraussetzung abhängig. Wenn die vorhandene ArbeitCANCELLEDoderFAILEDist, wird die neue Arbeit trotzdem ausgeführt.
Für periodische Arbeit geben Sie eine
ExistingPeriodicWorkPolicy an,
die zwei Optionen unterstützt: REPLACE und KEEP. Diese Optionen funktionieren genauso wie ihre Entsprechungen in der ExistingWorkPolicy.
Arbeit beobachten
Nachdem Sie Arbeit in die Warteschlange gestellt haben, können Sie den Status jederzeit prüfen, indem Sie WorkManager nach name, id oder einem zugehörigen 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 die
id der Arbeit, ihre Tags, ihren
aktuellen State und alle Ausgabedatasets mit
Result.success(outputData) enthält.
Mit den LiveData- und Flow
-Varianten der einzelnen Methoden können Sie Änderungen an der
WorkInfo beobachten, indem Sie einen Listener registrieren. Wenn Sie dem Nutzer beispielsweise eine Nachricht anzeigen möchten, wenn eine Arbeit erfolgreich abgeschlossen wurde, können Sie das so einrichten:
Kotlin
workManager.getWorkInfoByIdFlow(syncWorker.id)
.collect{ 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 in die Warteschlange gestellte Jobs mit
WorkQuery-Objekten. Mit WorkQuery können Sie Arbeit anhand einer Kombination aus Tag(s), Status und eindeutigem Arbeitsnamen abfragen.
Im folgenden Beispiel wird gezeigt, wie Sie alle Arbeiten mit dem Tag „syncTag“,
finden, die den Status FAILED oder CANCELLED haben und deren eindeutiger Arbeitsname
entweder „preProcess“ oder „sync“ ist.
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 einer WorkQuery wird mit den anderen Komponenten mit AND verknüpft. Jeder Wert in einer Komponente wird OR-ed. Beispiel: (name1 OR name2
OR ...) AND (tag1 OR tag2 OR ...) AND (state1 OR state2 OR ...).
WorkQuery funktioniert auch mit dem LiveData-Äquivalent,
getWorkInfosLiveData(),
und dem Flow-Äquivalent getWorkInfosFlow().
Arbeit abbrechen und beenden
Wenn Sie nicht mehr möchten, dass die zuvor in die Warteschlange gestellte Arbeit ausgeführt wird, können Sie sie abbrechen. Arbeit kann anhand von name, id oder einem zugehörigen 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");
Im Hintergrund prüft WorkManager den
State der Arbeit. Wenn die Arbeit bereits
abgeschlossenist,
passiert nichts. Andernfalls wird der Status der Arbeit in
CANCELLED geändert und die Arbeit
wird in Zukunft nicht ausgeführt. Alle
WorkRequest Jobs, die abhängig
von dieser Arbeit sind, werden
ebenfalls CANCELLED.
RUNNING Arbeit
erhält einen Aufruf an
ListenableWorker.onStopped().
Überschreiben Sie diese Methode, um potenzielle Bereinigungen zu verarbeiten. Weitere Informationen finden Sie unter Laufenden Worker
beenden.
Laufenden Worker beenden
Es gibt verschiedene Gründe, warum ein laufender Worker von WorkManager beendet werden kann:
- Sie haben explizit darum gebeten, ihn abzubrechen (z. B. durch Aufrufen von
WorkManager.cancelWorkById(UUID)). - Bei eindeutiger Arbeit,
haben Sie explizit ein neues
WorkRequestmit einerExistingWorkPolicyvonREPLACEin die Warteschlange gestellt. Das alteWorkRequestwird sofort als abgebrochen betrachtet. - Die Einschränkungen für Ihre Arbeit werden nicht mehr erfüllt.
- Das System hat Ihre App aus irgendeinem Grund angewiesen, die Arbeit zu beenden. Das kann passieren, wenn Sie die Ausführungsfrist von 10 Minuten überschreiten. Die Arbeit wird zu einem späteren Zeitpunkt zur Wiederholung geplant.
Unter diesen Bedingungen wird Ihr Worker beendet.
Sie sollten alle laufenden Arbeiten kooperativ abbrechen und alle Ressourcen freigeben, die Ihr Worker verwendet. Beispielsweise sollten Sie an dieser Stelle offene Handles für Datenbanken und Dateien schließen. Es gibt zwei Mechanismen, mit denen Sie feststellen können, wann Ihr Worker beendet wird.
onStopped()-Callback
WorkManager invokes
ListenableWorker.onStopped()
sobald Ihr Worker beendet wurde. Überschreiben Sie diese Methode, um alle Ressourcen zu schließen, die Sie möglicherweise verwenden.
isStopped()-Property
Sie können die
ListenableWorker.isStopped() Methode aufrufen, um zu prüfen, ob Ihr Worker bereits
beendet wurde. Wenn Sie in Ihrem Worker Vorgänge mit langer Ausführungszeit oder wiederholte Vorgänge ausführen, sollten Sie diese Property häufig prüfen und sie als Signal verwenden, um die Arbeit so schnell wie möglich zu beenden.
Hinweis: WorkManager ignoriert das
Result, das von einem Worker
festgelegt wurde, der das onStop-Signal erhalten hat, da der Worker bereits als
beendet betrachtet wird.