Im Startleitfaden wurde beschrieben, wie Sie eine WorkRequest erstellen und in die Warteschlange stellen.
In diesem Leitfaden erfahren Sie, wie Sie WorkRequest-Objekte für gängige Anwendungsfälle definieren und anpassen, z. B.:
- Einmalige und wiederkehrende Arbeiten planen
- Arbeitseinschränkungen festlegen, z. B. WLAN oder Aufladen erforderlich
- Mindestverzögerung bei der Ausführung von Aufgaben garantieren
- Strategien für Wiederholungsversuche und Backoff festlegen
- Eingabedaten an die Arbeit übergeben
- Zusammengehörige Aufgaben mithilfe von Tags gruppieren
Übersicht
In WorkManager wird Arbeit mit einem WorkRequest definiert. Wenn Sie mit WorkManager eine Aufgabe planen möchten, müssen Sie zuerst ein WorkRequest-Objekt erstellen und es dann in die Warteschlange stellen.
Kotlin
val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)
Java
WorkRequest myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest);
Das WorkRequest-Objekt enthält alle Informationen, die WorkManager benötigt, um Ihre Arbeit zu planen und auszuführen. Sie enthält Einschränkungen, die erfüllt sein müssen, damit Ihre Arbeit ausgeführt werden kann, Planungsinformationen wie Verzögerungen oder Wiederholungsintervalle, die Konfiguration für Wiederholungsversuche und möglicherweise Eingabedaten, wenn Ihre Arbeit davon abhängt.
WorkRequest selbst ist eine abstrakte Basisklasse. Es gibt zwei abgeleitete Implementierungen dieser Klasse, mit denen Sie die Anfrage erstellen können: OneTimeWorkRequest und PeriodicWorkRequest.
Wie die Namen schon sagen, ist OneTimeWorkRequest nützlich, um nicht wiederkehrende Aufgaben zu planen, während PeriodicWorkRequest besser geeignet ist, um Aufgaben zu planen, die sich in einem bestimmten Intervall wiederholen.
Einmalige Arbeit planen
Verwenden Sie für einfache Aufgaben, die keine zusätzliche Konfiguration erfordern, die statische Methode from:
Kotlin
val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)
Java
WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);
Für komplexere Aufgaben können Sie einen Builder verwenden:
Kotlin
val uploadWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWork>()
// Additional configuration
.build()
Java
WorkRequest uploadWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
// Additional configuration
.build();
Express-Jobs planen
In WorkManager 2.7.0 wurde das Konzept der Express-Jobs eingeführt. So kann WorkManager wichtige Aufgaben ausführen, während das System den Zugriff auf Ressourcen besser steuern kann.
Express-Jobs zeichnen sich durch folgende Merkmale aus:
- Bedeutung: Express-Jobs eignen sich für Aufgaben, die für den Nutzer wichtig sind oder von ihm initiiert werden.
- Geschwindigkeit: Express-Jobs eignen sich am besten für kurze Aufgaben, die sofort gestartet und innerhalb weniger Minuten abgeschlossen werden.
- Kontingente: Ein Kontingent auf Systemebene, das die Ausführungszeit im Vordergrund begrenzt, bestimmt, ob ein Express-Job gestartet werden kann.
- Energieverwaltung: Einschränkungen der Energieverwaltung, z. B. der Energiesparmodus und der Stromsparmodus, wirken sich weniger wahrscheinlich auf Express-Jobs aus.
- Latenz: Das System führt Express-Jobs sofort aus, sofern die aktuelle Arbeitslast des Systems dies zulässt. Das bedeutet, dass sie latenzempfindlich sind und nicht für eine spätere Ausführung geplant werden können.
Ein potenzieller Anwendungsfall für Express-Jobs könnte eine Chat-App sein, wenn der Nutzer eine Nachricht oder ein angehängtes Bild senden möchte. Auch für eine App, die einen Zahlungs- oder Abo-Ablauf verarbeitet, kann ein Express-Job sinnvoll sein. Das liegt daran, dass diese Aufgaben für den Nutzer wichtig sind, schnell im Hintergrund ausgeführt werden, sofort beginnen müssen und auch dann weiter ausgeführt werden sollten, wenn der Nutzer die App schließt.
Kontingente
Das System muss einem Express-Job Ausführungszeit zuweisen, bevor er ausgeführt werden kann. Die Ausführungszeit ist nicht unbegrenzt. Stattdessen erhält jede Anwendung ein Kontingent an Ausführungszeit. Wenn Ihre App die Ausführungszeit aufgebraucht und das zugewiesene Kontingent erreicht hat, können Sie keine Express-Jobs mehr ausführen, bis das Kontingent aktualisiert wird. So kann Android die Ressourcen besser zwischen den Anwendungen verteilen.
Die für eine App verfügbare Ausführungszeit hängt vom Stand-by-Bucket und der Wichtigkeit des Prozesses ab.
Sie können festlegen, was passiert, wenn das Ausführungskontingent die sofortige Ausführung eines Express-Jobs nicht zulässt. Weitere Informationen finden Sie in den folgenden Snippets.
Express-Jobs ausführen
Ab WorkManager 2.7 kann Ihre App setExpedited() aufrufen, um zu deklarieren, dass ein WorkRequest so schnell wie möglich mit einem Express-Job ausgeführt werden soll. Das folgende Code-Snippet zeigt ein Beispiel für die Verwendung von setExpedited():
Kotlin
val request = OneTimeWorkRequestBuilder<SyncWorker>()
<b>.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)</b>
.build()
WorkManager.getInstance(context)
.enqueue(request)
Java
OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>()
.setInputData(inputData)
<b>.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)</b>
.build();
In diesem Beispiel initialisieren wir eine Instanz von OneTimeWorkRequest und rufen setExpedited() dafür auf. Diese Anfrage wird dann zu einem Express-Job. Wenn das Kontingent es zulässt, wird sie sofort im Hintergrund ausgeführt. Wenn das Kontingent aufgebraucht ist, gibt der Parameter OutOfQuotaPolicy an, dass die Anfrage als normaler, nicht beschleunigter Job ausgeführt werden soll.
Abwärtskompatibilität und Dienste im Vordergrund
Um die Abwärtskompatibilität für Express-Jobs aufrechtzuerhalten, führt WorkManager möglicherweise einen Dienst im Vordergrund auf Plattformversionen aus, die älter als Android 12 sind. Dienste im Vordergrund können dem Nutzer eine Benachrichtigung anzeigen.
Mit den Methoden getForegroundInfoAsync() und getForegroundInfo() in Ihrem Worker kann WorkManager eine Benachrichtigung anzeigen, wenn Sie setExpedited() vor Android 12 aufrufen.
Alle ListenableWorker müssen die Methode getForegroundInfo implementieren, wenn Sie anfordern möchten, dass die Aufgabe als Express-Job ausgeführt wird.
Wenn Sie Android 12 oder höher verwenden, sind Dienste im Vordergrund über die entsprechende setForeground-Methode weiterhin verfügbar.
Worker
Die Worker wissen nicht, ob die von ihnen ausgeführte Arbeit beschleunigt wird oder nicht. Worker können jedoch in einigen Android-Versionen eine Benachrichtigung anzeigen, wenn ein WorkRequest beschleunigt wurde.
Dazu stellt WorkManager die Methode getForegroundInfoAsync() bereit, die Sie implementieren müssen, damit WorkManager bei Bedarf eine Benachrichtigung zum Starten eines ForegroundService für Sie anzeigen kann.
CoroutineWorker
Wenn du ein CoroutineWorker verwendest, musst du getForegroundInfo() implementieren. Anschließend übergeben Sie sie an setForeground() in doWork(). Dadurch wird die Benachrichtigung in Android-Versionen vor Android 12 erstellt.
Dazu ein Beispiel:
class ExpeditedWorker(appContext: Context, workerParams: WorkerParameters):
CoroutineWorker(appContext, workerParams) {
override suspend fun getForegroundInfo(): ForegroundInfo {
return ForegroundInfo(
NOTIFICATION_ID, createNotification()
)
}
override suspend fun doWork(): Result {
TODO()
}
private fun createNotification() : Notification {
TODO()
}
}
Kontingentrichtlinien
Du kannst festlegen, was mit Express-Jobs passiert, wenn deine App ihr Ausführungskontingent erreicht. Um fortzufahren, können Sie setExpedited() übergeben:
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST, wodurch der Job als normale Arbeitsanfrage ausgeführt wird. Das vorherige Snippet veranschaulicht dies.OutOfQuotaPolicy.DROP_WORK_REQUEST, wodurch die Anfrage abgebrochen wird, wenn nicht genügend Kontingent vorhanden ist.
Zurückgestellte Express-Jobs
Das System versucht, einen bestimmten Express-Job so schnell wie möglich nach dem Aufruf auszuführen. Wie bei anderen Arten von Jobs kann das System jedoch den Start neuer Express-Jobs verzögern, z. B. in den folgenden Fällen:
- Last: Die Systemlast ist zu hoch. Das kann passieren, wenn bereits zu viele Jobs ausgeführt werden oder das System nicht genügend Arbeitsspeicher hat.
- Kontingent: Das Kontingentlimit für Express-Jobs wurde überschritten. Für Express-Jobs wird ein Kontingentsystem verwendet, das auf den App-Standby-Buckets basiert und die maximale Ausführungszeit innerhalb eines rollierenden Zeitfensters begrenzt. Die Kontingente für Express-Jobs sind restriktiver als die für andere Arten von Hintergrundjobs.
Regelmäßige Aufgaben planen
In Ihrer App müssen bestimmte Aufgaben möglicherweise regelmäßig ausgeführt werden. Beispielsweise möchten Sie Ihre Daten regelmäßig sichern, neue Inhalte in Ihre App herunterladen oder Logs auf einen Server hochladen.
So verwenden Sie die PeriodicWorkRequest, um ein WorkRequest-Objekt zu erstellen, das regelmäßig ausgeführt wird:
Kotlin
val saveRequest =
PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
// Additional configuration
.build()
Java
PeriodicWorkRequest saveRequest =
new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
// Constraints
.build();
In diesem Beispiel wird die Arbeit mit einem Intervall von einer Stunde geplant.
Das Intervall ist die Mindestzeit zwischen Wiederholungen. Der genaue Zeitpunkt, zu dem der Worker ausgeführt wird, hängt von den Einschränkungen ab, die Sie in Ihrem WorkRequest-Objekt verwenden, und von den vom System durchgeführten Optimierungen.
Flexible Ausführungsintervalle
Wenn die Art Ihrer Arbeit es erfordert, dass die Ausführungszeitpunkte sensibel sind, können Sie Ihre PeriodicWorkRequest so konfigurieren, dass sie innerhalb eines flexiblen Zeitraums innerhalb jedes Intervallzeitraums ausgeführt wird, wie in Abbildung 1 dargestellt.

Abbildung 1. Das Diagramm zeigt sich wiederholende Intervalle mit dem flexiblen Zeitraum, in dem die Arbeit ausgeführt werden kann.
Wenn Sie eine regelmäßige Aufgabe mit einem flexiblen Zeitraum definieren möchten, übergeben Sie beim Erstellen des PeriodicWorkRequest einen flexInterval zusammen mit dem repeatInterval. Der flexible Zeitraum beginnt um repeatInterval - flexInterval und dauert bis zum Ende des Intervalls.
Das folgende Beispiel zeigt eine regelmäßige Aufgabe, die in den letzten 15 Minuten jeder Stunde ausgeführt werden kann.
Kotlin
val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
1, TimeUnit.HOURS, // repeatInterval (the period cycle)
15, TimeUnit.MINUTES) // flexInterval
.build()
Java
WorkRequest saveRequest =
new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
1, TimeUnit.HOURS,
15, TimeUnit.MINUTES)
.build();
Das Wiederholungsintervall muss größer oder gleich PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS und das flexible Intervall muss größer oder gleich PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS` sein.
Auswirkung von Einschränkungen auf regelmäßige Aufgaben
Sie können Einschränkungen auf regelmäßige Aufgaben anwenden. Sie können Ihrer Arbeitsanfrage beispielsweise eine Einschränkung hinzufügen, sodass die Arbeit nur ausgeführt wird, wenn das Gerät des Nutzers aufgeladen wird. In diesem Fall wird der PeriodicWorkRequest erst ausgeführt, wenn diese Bedingung erfüllt ist, auch wenn das definierte Wiederholungsintervall abgelaufen ist. Dies kann dazu führen, dass eine bestimmte Ausführung Ihrer Arbeit verzögert oder sogar übersprungen wird, wenn die Bedingungen nicht innerhalb des Ausführungsintervalls erfüllt werden.
Arbeitsbeschränkungen
Constraints sorgt dafür, dass die Arbeit verschoben wird, bis die optimalen Bedingungen erfüllt sind. Die folgenden Einschränkungen sind für WorkManager verfügbar:
| NetworkType | Schränkt den Netzwerktyp ein, der für die Ausführung Ihrer Arbeit erforderlich ist.
Zum Beispiel WLAN (UNMETERED).
|
| BatteryNotLow | Wenn „true“ festgelegt ist, wird die Arbeit nicht ausgeführt, wenn sich das Gerät im Energiesparmodus befindet. |
| RequiresCharging | Wenn „true“ festgelegt ist, wird die Arbeit nur ausgeführt, wenn das Gerät geladen wird. |
| DeviceIdle | Wenn „true“ festgelegt ist, muss das Gerät des Nutzers inaktiv sein, bevor die Arbeit ausgeführt wird. Das kann nützlich sein, um Batchvorgänge auszuführen, die sich sonst negativ auf die Leistung anderer Apps auswirken könnten, die aktiv auf dem Gerät des Nutzers ausgeführt werden. |
| StorageNotLow | Wenn diese Option auf „true“ gesetzt ist, wird die Arbeit nicht ausgeführt, wenn der Speicherplatz des Nutzers auf dem Gerät zu gering ist. |
Wenn Sie eine Reihe von Einschränkungen erstellen und mit einer Arbeit verknüpfen möchten, erstellen Sie eine Constraints-Instanz mit dem Constraints.Builder() und weisen Sie sie Ihrer WorkRequest.Builder() zu.
Mit dem folgenden Code wird beispielsweise eine Arbeitsanfrage erstellt, die nur ausgeführt wird, wenn das Gerät des Nutzers sowohl aufgeladen wird als auch mit dem WLAN verbunden ist:
Kotlin
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build()
val myWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWork>()
.setConstraints(constraints)
.build()
Java
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresCharging(true)
.build();
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.setConstraints(constraints)
.build();
Wenn mehrere Einschränkungen angegeben sind, wird die Arbeit nur ausgeführt, wenn alle Einschränkungen erfüllt sind.
Wenn eine Einschränkung während der Ausführung der Arbeit nicht mehr erfüllt wird, beendet WorkManager den Worker. Die Arbeit wird dann wiederholt, wenn alle Einschränkungen erfüllt sind.
Verzögerte Arbeit
Wenn Ihre Arbeit keine Einschränkungen hat oder alle Einschränkungen erfüllt sind, wenn Ihre Arbeit in die Warteschlange gestellt wird, kann das System die Arbeit sofort ausführen. Wenn die Arbeit nicht sofort ausgeführt werden soll, können Sie festlegen, dass sie erst nach einer Mindestverzögerung gestartet wird.
Hier ist ein Beispiel dafür, wie Sie Ihre Arbeit so einrichten, dass sie mindestens 10 Minuten nach dem Einreihen in die Warteschlange ausgeführt wird.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setInitialDelay(10, TimeUnit.MINUTES)
.build()
Java
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.setInitialDelay(10, TimeUnit.MINUTES)
.build();
Im Beispiel wird gezeigt, wie Sie eine anfängliche Verzögerung für eine OneTimeWorkRequest festlegen. Sie können aber auch eine anfängliche Verzögerung für eine PeriodicWorkRequest festlegen. In diesem Fall wird nur die erste Ausführung der regelmäßigen Arbeit verzögert.
Richtlinie für Wiederholungsversuche und Backoff
Wenn Sie möchten, dass WorkManager die Arbeit wiederholt, können Sie Result.retry() von Ihrem Worker zurückgeben. Ihre Arbeit wird dann gemäß einer Backoff-Verzögerung und einer Backoff-Richtlinie neu geplant.
Die Backoff-Verzögerung gibt die Mindestwartezeit an, bevor die Arbeit nach dem ersten Versuch wiederholt wird. Dieser Wert darf nicht kleiner als 10 Sekunden (oder MIN_BACKOFF_MILLIS) sein.
Die Backoff-Richtlinie definiert, wie sich die Backoff-Verzögerung im Laufe der Zeit für nachfolgende Wiederholungsversuche erhöhen soll. WorkManager unterstützt zwei Backoff-Richtlinien:
LINEARundEXPONENTIAL.
Für jede Arbeitsanfrage gibt es eine Backoff-Richtlinie und eine Backoff-Verzögerung. Die Standardrichtlinie ist EXPONENTIAL mit einer Verzögerung von 30 Sekunden. Sie können dies jedoch in der Konfiguration Ihrer Arbeitsanfrage überschreiben.
Hier ist ein Beispiel für die Anpassung der Backoff-Verzögerung und der Richtlinie.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.setBackoffCriteria(
BackoffPolicy.LINEAR,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build()
Java
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.setBackoffCriteria(
BackoffPolicy.LINEAR,
WorkRequest.MIN_BACKOFF_MILLIS,
TimeUnit.MILLISECONDS)
.build();
In diesem Beispiel ist die minimale Backoff-Verzögerung auf den zulässigen Mindestwert von 10 Sekunden festgelegt. Da die Richtlinie LINEAR ist, erhöht sich das Wiederholungsintervall bei jedem neuen Versuch um etwa 10 Sekunden. Beispiel: Wenn die erste Ausführung mit Result.retry() abgeschlossen wird, wird sie nach 10 Sekunden noch einmal versucht, gefolgt von 20, 30, 40 usw., wenn die Arbeit nach nachfolgenden Versuchen weiterhin Result.retry() zurückgibt. Wenn die Backoff-Richtlinie auf EXPONENTIAL festgelegt wäre, würde die Wiederholungsdauer eher 20, 40 und 80 betragen.
Aufgaben taggen
Jede Arbeitsanfrage hat eine eindeutige Kennung, mit der die Arbeit später identifiziert werden kann, um sie abzubrechen oder ihren Fortschritt zu beobachten.
Wenn Sie eine Gruppe logisch zusammengehöriger Arbeitselemente haben, kann es auch hilfreich sein, diese Arbeitselemente zu taggen. Mit Tags können Sie eine Gruppe von Arbeitsanfragen zusammen verwalten.
Beispielsweise bricht WorkManager.cancelAllWorkByTag(String) alle Arbeitsanfragen mit einem bestimmten Tag ab und WorkManager.getWorkInfosByTag(String) gibt eine Liste der WorkInfo-Objekte zurück, mit denen der aktuelle Arbeitsstatus ermittelt werden kann.
Der folgende Code zeigt, wie Sie Ihrer Arbeit ein „cleanup“-Tag hinzufügen können:
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
.addTag("cleanup")
.build()
Java
WorkRequest myWorkRequest =
new OneTimeWorkRequest.Builder(MyWork.class)
.addTag("cleanup")
.build();
Schließlich können einer einzelnen Arbeitsanfrage mehrere Tags hinzugefügt werden. Intern werden diese Tags als eine Reihe von Strings gespeichert. Mit WorkInfo.getTags() können Sie die Tags abrufen, die mit WorkRequest verknüpft sind.
In der Klasse Worker können Sie die Tags mit ListenableWorker.getTags() abrufen.
Eingabedaten zuweisen
Für Ihre Arbeit sind möglicherweise Eingabedaten erforderlich. Für eine Aufgabe, bei der ein Bild hochgeladen wird, ist beispielsweise der URI des hochzuladenden Bildes als Eingabe erforderlich.
Eingabewerte werden als Schlüssel/Wert-Paare in einem Data-Objekt gespeichert und können in der Arbeitsanfrage festgelegt werden. WorkManager liefert die Eingabe-Data an Ihre Arbeit, wenn sie ausgeführt wird. Die Klasse Worker kann durch Aufrufen von Worker.getInputData() auf die Eingabeargumente zugreifen. Der folgende Code zeigt, wie Sie eine Worker-Instanz erstellen, die Eingabedaten erfordert, und wie Sie sie in Ihrer Arbeitsanfrage senden.
Kotlin
// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
: Worker(appContext, workerParams) {
override fun doWork(): Result {
val imageUriInput =
inputData.getString("IMAGE_URI") ?: return Result.failure()
uploadFile(imageUriInput)
return Result.success()
}
...
}
// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
.setInputData(workDataOf(
"IMAGE_URI" to "http://..."
))
.build()
Java
// Define the Worker requiring input
public class UploadWork extends Worker {
public UploadWork(Context appContext, WorkerParameters workerParams) {
super(appContext, workerParams);
}
@NonNull
@Override
public Result doWork() {
String imageUriInput = getInputData().getString("IMAGE_URI");
if(imageUriInput == null) {
return Result.failure();
}
uploadFile(imageUriInput);
return Result.success();
}
...
}
// Create a WorkRequest for your Worker and sending it input
WorkRequest myUploadWork =
new OneTimeWorkRequest.Builder(UploadWork.class)
.setInputData(
new Data.Builder()
.putString("IMAGE_URI", "http://...")
.build()
)
.build();
Ebenso können Sie die Klasse Data verwenden, um einen Rückgabewert auszugeben.
Nächste Schritte
Auf der Seite Status und Beobachtung erfahren Sie mehr über Arbeitsstatus und wie Sie den Fortschritt Ihrer Arbeit überwachen können.