Aufgaben aktualisieren, die sich bereits in die Warteschlange eingereiht haben

Mit WorkManager können Sie ein WorkRequest aktualisieren, nachdem Sie es bereits in die Warteschlange gestellt haben. Dies ist oft bei größeren Anwendungen erforderlich, in denen Einschränkungen häufig geändert werden oder die Worker spontan aktualisiert werden müssen. Ab WorkManager Version 2.8.0 wird die updateWork() API verwendet.

Mit der Methode updateWork() können Sie bestimmte Aspekte einer WorkRequest im laufenden Betrieb ändern, ohne dass Sie eine neue Anfrage manuell abbrechen und in die Warteschlange stellen müssen. Dies vereinfacht den Entwicklungsprozess erheblich.

Aufgaben nicht abbrechen

Im Allgemeinen sollten Sie es vermeiden, eine vorhandene WorkRequest abzubrechen und eine neue in die Warteschlange zu stellen. Dies kann dazu führen, dass die Anwendung bestimmte Aufgaben wiederholt, und Sie müssen möglicherweise eine beträchtliche Menge an zusätzlichem Code schreiben.

Die folgenden Beispiele zeigen, wo das Abbrechen einer WorkRequest Probleme verursachen kann:

  • Backend-Anfrage: Wenn Sie eine Worker abbrechen, während eine Nutzlast zum Senden an den Server berechnet wird, muss der neue Worker von vorn beginnen und die potenziell teure Nutzlast neu berechnen.
  • Planung:Wenn Sie eine PeriodicWorkRequest abbrechen und die neue PeriodicWorkRequest nach demselben Zeitplan ausgeführt werden soll, müssen Sie eine Zeitverschiebung berechnen, damit die neue Ausführungszeit mit der vorherigen Arbeitsanfrage übereinstimmt.

Mit der updateWork() API können Sie die Einschränkungen einer Arbeitsanfrage und andere Parameter aktualisieren, ohne die Anfrage abbrechen und eine neue in die Warteschlange stellen zu müssen.

Wann Sie die Arbeit abbrechen sollten

Es gibt Fälle, in denen Sie WorkRequest direkt abbrechen sollten, anstatt updateWork() aufzurufen. Dies sollten Sie tun, wenn Sie den grundlegenden Charakter der Arbeit, die Sie in die Warteschlange gestellt haben, ändern möchten.

Wann die Arbeitsadresse aktualisiert werden sollte

Stellen Sie sich eine Foto-App vor, mit der täglich die Fotos des Nutzers gesichert werden. Dafür wurde ein PeriodicWorkRequest in die Warteschlange gestellt. WorkRequest hat Einschränkungen, die es erforderlich machen, dass das Gerät aufgeladen wird und mit dem WLAN verbunden ist.

Allerdings lädt der Nutzer sein Gerät mit einem Schnellladegerät nur 20 Minuten pro Tag auf. In diesem Fall kann die App WorkRequest aktualisieren, um die Ladebeschränkung zu lockern. So können die Fotos auch dann hochgeladen werden, wenn das Gerät nicht vollständig geladen ist.

In diesem Fall können Sie mit der Methode updateWork() die Einschränkungen der Arbeitsanfrage aktualisieren.

Aufgaben aktualisieren

Die Methode updateWork() bietet eine einfache Möglichkeit zum Aktualisieren einer vorhandenen WorkRequest, ohne dass eine neue abgebrochen und in die Warteschlange gestellt werden muss.

So verwenden Sie die Aktualisierung von Aufgaben in der Warteschlange:

  1. Vorhandene ID für Aufgaben in der Warteschlange abrufen: Rufen Sie die ID der WorkRequest ab, die Sie aktualisieren möchten. Sie können diese ID mit einer der getWorkInfo APIs abrufen oder die ID aus der ursprünglichen WorkRequest manuell speichern, um sie später in der öffentlichen Property WorkRequest.id abzurufen, bevor sie in die Warteschlange gestellt wird.
  2. Create new WorkRequest: Erstellen Sie eine neue WorkRequest und verwenden Sie WorkRequest.Builder.setID(), um die ID entsprechend der vorhandenen WorkRequest festzulegen.
  3. Einschränkungen festlegen: Verwenden Sie WorkRequest.Builder.setConstraints(), um die neuen WorkManager-Einschränkungen zu übergeben.
  4. UpdateWork aufrufen: Übergib die neue WorkRequest an updateWork().

Arbeitsbeispiel aktualisieren

Das folgende Beispiel-Code-Snippet in Kotlin zeigt, wie mit der Methode updateWork() die Akkubeschränkungen einer WorkRequest geändert werden können, die zum Hochladen von Fotos verwendet wird:

suspend fun updatePhotoUploadWork() {
    // Get instance of WorkManager.
    val workManager = WorkManager.getInstance(context)

    // Retrieve the work request ID. In this example, the work being updated is unique
    // work so we can retrieve the ID using the unique work name.
    val photoUploadWorkInfoList = workManager.getWorkInfosForUniqueWork(
        PHOTO_UPLOAD_WORK_NAME
    ).await()

    val existingWorkRequestId = photoUploadWorkInfoList.firstOrNull()?.id ?: return

    // Update the constraints of the WorkRequest to not require a charging device.
    val newConstraints = Constraints.Builder()
        // Add other constraints as required here.
        .setRequiresCharging(false)
        .build()

    // Create new WorkRequest from existing Worker, new constraints, and the id of the old WorkRequest.
    val updatedWorkRequest: WorkRequest =
        OneTimeWorkRequestBuilder<MyWorker>()
            .setConstraints(newConstraints)
            .setId(existingWorkRequestId)
            .build()

    // Pass the new WorkRequest to updateWork().
    workManager.updateWork(updatedWorkRequest)
}

Ergebnis verarbeiten

updateWork() gibt ein ListenableFuture<UpdateResult> zurück. Die angegebene UpdateResult kann einen der verschiedenen Werte enthalten, die angeben, ob WorkManager Ihre Änderungen anwenden konnte. Es zeigt auch an, wann die Änderung übernommen wurde.

Weitere Informationen finden Sie in der Referenz zu updateWork() und UpdateResult in der Referenz.

Arbeit mit Generationen im Blick behalten

Jedes Mal, wenn Sie eine WorkRequest aktualisieren, erhöht sich die generation um eins. So können Sie genau verfolgen, welche WorkRequest derzeit in die Warteschlange eingereiht wird. Generierungen bieten Ihnen mehr Kontrolle beim Beobachten, Tracing und Testen von Arbeitsanfragen.

So rufen Sie die Generierung eines WorkRequest ab:

  1. WorkInfo: Rufen Sie WorkManager.getWorkInfoById() auf, um eine Instanz von WorkInfo abzurufen, die Ihrem WorkRequest entspricht.
    • Sie können eine von mehreren Methoden aufrufen, die ein WorkInfo zurückgeben. Weitere Informationen finden Sie in der WorkManager-Referenz.
  2. getGeneration: Rufen Sie getGeneration() für die Instanz von WorkInfo auf. Der zurückgegebene Int entspricht der Generation des WorkRequest.
    • Es gibt kein Feld und keine Eigenschaft für die Generierung, sondern nur die Methode WorkInfo.getGeneration().

Beispiel für Track-Generierung

Im Folgenden finden Sie eine Beispielimplementierung des oben beschriebenen Workflows zum Abrufen der Generierung einer WorkRequest.

// Get instance of WorkManager.
val workManager = WorkManager.getInstance(context)

// Retrieve WorkInfo instance.
val workInfo = workManager.getWorkInfoById(oldWorkRequestId)

// Call getGeneration to retrieve the generation.
val generation = workInfo.getGeneration()

Richtlinien für die Aktualisierung von Arbeitsergebnissen

Zuvor wurde für die Aktualisierung regelmäßiger Arbeiten empfohlen, ein PeriodicWorkRequest mit der Richtlinie ExistingPeriodicWorkPolicy.REPLACE in die Warteschlange zu stellen. Wenn es eine ausstehende PeriodicWorkRequest mit derselben eindeutigen id gibt, wird die neue Arbeitsanfrage abgebrochen und gelöscht. Diese Richtlinie wurde zugunsten des Workflows mit ExistingPeriodicWorkPolicy.UPDATE verworfen.

Wenn du beispielsweise enqueueUniquePeriodicWork mit einer PeriodicWorkRequest verwendest, kannst du das neue PeriodicWorkRequest mit der Richtlinie ExistingPeriodicWorkPolicy.UPDATE initialisieren. Gibt es eine ausstehende PeriodicWorkRequest mit demselben eindeutigen Namen, wird sie von WorkManager auf die neue Spezifikation aktualisiert. Für diesen Workflow ist die Verwendung von updateWork() nicht erforderlich.