Zaktualizuj zadania, które są już w kolejce

WorkManager pozwala zaktualizować element WorkRequest znajdujący się już w kolejce. Często jest to konieczne w przypadku większych aplikacji, które często zmieniają ograniczenia lub muszą na bieżąco aktualizować pracowników. Od wersji 2.8.0 można to robić za pomocą interfejsu API updateWork().

Metoda updateWork() pozwala na bieżąco zmieniać niektóre aspekty elementu WorkRequest bez konieczności ręcznego anulowania i dodania nowego elementu do kolejki. To znacznie upraszcza proces programowania.

Unikaj anulowania pracy

Należy unikać anulowania istniejącego żądania WorkRequest i dodania nowego do kolejki. Może to spowodować powtarzanie niektórych zadań przez aplikację i wymagać znacznego napisania dodatkowego kodu.

Oto przykłady sytuacji, w których anulowanie żądania WorkRequest może powodować problemy:

  • Żądanie backendu: jeśli anulujesz Worker podczas przetwarzania ładunku do wysłania na serwer, nowy ładunek Worker musi uruchomić się od nowa i ponownie obliczyć potencjalnie kosztowny ładunek.
  • Harmonogram: jeśli anulujesz zadanie PeriodicWorkRequest i chcesz, aby nowa klasa PeriodicWorkRequest była wykonywana zgodnie z tym samym harmonogramem, musisz obliczyć przesunięcie czasu, aby nowy czas wykonania był zgodny z poprzednim żądaniem.

Interfejs updateWork() API umożliwia aktualizowanie ograniczeń i innych parametrów żądania roboczego bez konieczności jego anulowania i umienienia w kolejce.

Kiedy anulować zadanie

Są przypadki, w których należy anulować żądanie WorkRequest bezpośrednio, zamiast wywoływać metodę updateWork(). To właśnie należy zrobić, gdy chcesz zmienić podstawowy charakter utworu umieszczonego w kolejce.

Kiedy aktualizować dane służbowe

Wyobraź sobie aplikację do zdjęć, która codziennie wykonuje kopię zapasową zdjęć użytkownika. Dodała do tego zadanie PeriodicWorkRequest. WorkRequest ma ograniczenia, które wymagają ładowania urządzenia i połączenia z Wi-Fi.

Jednak użytkownik korzysta z szybkiej ładowarki, aby ładować urządzenie tylko przez 20 minut dziennie. W takiej sytuacji aplikacja może chcieć zaktualizować WorkRequest, aby złagodzić ograniczenie ładowania, tak aby nadal mogła przesyłać zdjęcia nawet wtedy, gdy urządzenie nie jest w pełni naładowane.

W takiej sytuacji możesz użyć metody updateWork(), aby zaktualizować ograniczenia żądania roboczego.

Jak zaktualizować adres służbowy

Metoda updateWork() pozwala w prosty sposób zaktualizować istniejący element WorkRequest bez konieczności anulowania i dodania nowego elementu do kolejki.

Aby użyć zadań w kolejce aktualizacji, wykonaj te czynności:

  1. Pobierz istniejący identyfikator zadania umieszczonego w kolejce: uzyskaj identyfikator żądania WorkRequest, które chcesz zaktualizować. Możesz pobrać ten identyfikator za pomocą dowolnego interfejsu API getWorkInfo lub ręcznie zachować identyfikator z początkowego żądania WorkRequest do późniejszego pobrania w usłudze publicznej WorkRequest.id przed umieszczeniem go w kolejce.
  2. Utwórz nowe żądanie WorkRequest: utwórz nowe żądanie WorkRequest i użyj WorkRequest.Builder.setID(), aby ustawić jego identyfikator tak, aby był zgodny z istniejącym identyfikatorem WorkRequest.
  3. Ustaw ograniczenia: użyj WorkRequest.Builder.setConstraints(), aby przekazać nowe ograniczenia WorkManagera.
  4. Wywołanie updateWork: przekaż nowe żądanie WorkRequest do zadania updateWork().

Aktualizowanie przykładowego profilu służbowego

Oto przykładowy fragment kodu w aplikacji Kotlin, który pokazuje, jak użyć metody updateWork() do zmiany ograniczeń związanych z baterią elementu WorkRequest używanego do przesyłania zdjęć:

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)
}

Obsługa wyniku

updateWork() zwraca wartość ListenableFuture<UpdateResult>. Podana wartość UpdateResult może mieć jedną z kilku wartości, które określają, czy usługa WorkManager mogła zastosować Twoje zmiany. Pokazuje też, kiedy można było zastosować zmianę.

Więcej informacji znajdziesz w materiałach updateWork() oraz UpdateResult.

Śledzenie pracy z pokoleniami

Za każdym razem, gdy zaktualizujesz element WorkRequest, jego generacja zwiększa się o 1. Pozwoli Ci to śledzić dokładnie, który element WorkRequest jest obecnie w kolejce. Pokolenia zapewniają większą kontrolę nad obserwowaniem, śledzeniem i testowaniem żądań pracy.

Aby wygenerować WorkRequest, wykonaj te czynności:

  1. WorkInfo: wywołaj WorkManager.getWorkInfoById(), aby pobrać wystąpienie WorkInfo odpowiadające Twojemu WorkRequest.
    • Możesz wywołać jedną z kilku metod, które zwracają wartość WorkInfo. Więcej informacji znajdziesz w dokumentacji WorkManagera.
  2. getGeneration: wywołaj getGeneration() w instancji WorkInfo. Zwrócony Int odpowiada wygenerowaniu WorkRequest.
    • Pamiętaj, że nie ma pola ani właściwości generowania, a jedynie metoda WorkInfo.getGeneration().

Przykład generowania ścieżki

Poniżej znajduje się przykładowa implementacja opisanego powyżej przepływu pracy służącego do pobierania generowania obiektu 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()

Zasady aktualizowania informacji o pracy

Wcześniej zalecanym rozwiązaniem w przypadku aktualizowania okresowych zadań było umieszczenie elementu PeriodicWorkRequest w kolejce za pomocą zasady ExistingPeriodicWorkPolicy.REPLACE. Jeśli było oczekujące żądanie PeriodicWorkRequest z tym samym unikalnym identyfikatorem id, nowe zgłoszenie zadania zostałoby anulowane i usunięte. Ta zasada została wycofana i zastąpiona przepływem pracy za pomocą ExistingPeriodicWorkPolicy.UPDATE.

Jeśli na przykład używasz enqueueUniquePeriodicWork z PeriodicWorkRequest, możesz zainicjować nowy tag PeriodicWorkRequest za pomocą zasady ExistingPeriodicWorkPolicy.UPDATE. Jeśli jest oczekująca instancja PeriodicWorkRequest o tej samej unikalnej nazwie, WorkManager zaktualizuje ją do nowej specyfikacji. Zgodnie z tym przepływem pracy nie musisz używać właściwości updateWork().