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 ładunekWorker
musi uruchomić się od nowa i ponownie obliczyć potencjalnie kosztowny ładunek. - Harmonogram: jeśli anulujesz zadanie
PeriodicWorkRequest
i chcesz, aby nowa klasaPeriodicWorkRequest
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:
- 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 publicznejWorkRequest.id
przed umieszczeniem go w kolejce. - Utwórz nowe żądanie WorkRequest: utwórz nowe żądanie
WorkRequest
i użyjWorkRequest.Builder.setID()
, aby ustawić jego identyfikator tak, aby był zgodny z istniejącym identyfikatoremWorkRequest
. - Ustaw ograniczenia: użyj
WorkRequest.Builder.setConstraints()
, aby przekazać nowe ograniczenia WorkManagera. - 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:
- WorkInfo: wywołaj
WorkManager.getWorkInfoById()
, aby pobrać wystąpienieWorkInfo
odpowiadające TwojemuWorkRequest
.- Możesz wywołać jedną z kilku metod, które zwracają wartość
WorkInfo
. Więcej informacji znajdziesz w dokumentacji WorkManagera.
- Możesz wywołać jedną z kilku metod, które zwracają wartość
- getGeneration: wywołaj
getGeneration()
w instancjiWorkInfo
. ZwróconyInt
odpowiada wygenerowaniuWorkRequest
.- Pamiętaj, że nie ma pola ani właściwości generowania, a jedynie metoda
WorkInfo.getGeneration()
.
- Pamiętaj, że nie ma pola ani właściwości generowania, a jedynie metoda
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()
.