W przewodniku dla początkujących opisaliśmy, jak utworzyć proste WorkRequest
.
i umieść w kolejce.
Z tego przewodnika dowiesz się, jak definiować i dostosowywać obiekty WorkRequest
dotyczące typowych przypadków użycia, na przykład:
- Planowanie zadań jednorazowych i cyklicznych
- określać ograniczenia pracy, np. wymagać Wi-Fi lub ładowania.
- Zagwarantowanie minimalnego opóźnienia w realizacji zadań
- Ustaw strategie ponawiania i wycofywania
- Przekazywanie danych wejściowych do pracy
- Grupuj powiązane działania za pomocą tagów
Omówienie
Praca jest określana w usłudze WorkManager za pomocą WorkRequest
. Aby
zaplanować pracę z usługą WorkManager. Najpierw trzeba utworzyć
WorkRequest
obiekt, a następnie umieść go w kolejce.
Kotlin
val myWorkRequest = ... WorkManager.getInstance(myContext).enqueue(myWorkRequest)
Java
WorkRequest myWorkRequest = ... WorkManager.getInstance(myContext).enqueue(myWorkRequest);
Obiekt WorkRequest zawiera wszystkie informacje potrzebne aplikacji WorkManager do planowanie i uruchamianie pracy. Obejmuje ograniczenia, które muszą być spełnione w przypadku prac do wykonania, informacje o harmonogramie, takie jak opóźnienia lub powtarzające się interwały, ponawianie próby konfiguracji i może uwzględniać dane wejściowe, jeśli są one wymagane w Twojej pracy.
Sama klasa WorkRequest
jest abstrakcyjną klasą bazową. Dostępne są 2
implementacji pochodnej tej klasy, których możesz użyć do utworzenia żądania,
OneTimeWorkRequest
i PeriodicWorkRequest
.
OneTimeWorkRequest
– jak sama nazwa wskazuje, jest przydatna do planowania
materiały, które nie powtarzają się, natomiast PeriodicWorkRequest
lepiej nadaje się do
planowania zadań, które powtarzają się w określonych odstępach czasu.
Planowanie zadania jednorazowego
W przypadku prostych zadań, które nie wymagają dodatkowej konfiguracji, użyj statycznego parametru
metoda from
:
Kotlin
val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)
Java
WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);
W przypadku bardziej złożonych zadań możesz użyć kreatora:
Kotlin
val uploadWorkRequest: WorkRequest = OneTimeWorkRequestBuilder<MyWork>() // Additional configuration .build()
Java
WorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) // Additional configuration .build();
Planowanie prac przyspieszonej
W aplikacji WorkManager 2.7.0 wprowadzono koncepcję przyspieszonej pracy. Dzięki temu WorkManager do wykonywania ważnych zadań, zapewniając jednocześnie większą kontrolę nad systemem i zwiększać dostęp do zasobów.
Przyspieszona praca wyróżnia się następującymi cechami:
- Ważność: przyspieszona praca jest odpowiednia do zadań, które są ważne dla użytkownika lub są inicjowane przez użytkownika.
- Szybkość: „szybka praca” najlepiej pasuje do krótkich zadań, które zaczynają się od razu. możesz zrobić to w ciągu kilku minut.
- Limity: limit na poziomie systemu, który ogranicza czas wykonywania na pierwszym planie. określa, czy można uruchomić przyspieszone zadanie.
- Zarządzanie zasilaniem: ograniczenia dotyczące zarządzania zasilaniem, np. Bateria. Oszczędzanie i uśpienie rzadziej wpływają na przyspieszoną pracę.
- Czas oczekiwania: system natychmiast wykonuje przyspieszoną pracę, pod warunkiem że jest to możliwe w bieżącym zadaniu systemu. Oznacza to, że opóźnienia są poufne i nie można ich zaplanować do późniejszego wykonania.
Użycie przyspieszonej pracy może być np. w aplikacji do obsługi czatu, chce wysłać wiadomość lub załączony obraz. Podobnie aplikacja, która obsługuje w procesie płatności lub subskrypcji możesz też skorzystać z procesu przyspieszonego. To jest ponieważ są one ważne dla użytkownika, należy je szybko wykonać w tle, muszą rozpoczynać się natychmiast i powinny być nadal wykonywane nawet wtedy, użytkownik zamyka aplikację.
Limity
System musi przydzielić czas wykonywania do szybszego zadania, zanim może działać. Czas wykonywania nie jest nieograniczony. Każda aplikacja otrzymuje limit czas wykonywania. Gdy aplikacja wykorzysta czas wykonywania i osiągnie przydzielony limit, nie możesz wykonywać przyspieszonej pracy, dopóki limit odświeża się. Dzięki temu Android może efektywniej równoważyć zasoby aplikacji.
Czas wykonywania dostępny dla aplikacji zależy od zasobnik w trybie gotowości i znaczenie procesu.
Możesz określić, co się dzieje, gdy limit wykonania nie pozwala na zadanie przyspieszone do uruchomienia. Szczegóły znajdziesz w poniższych fragmentach kodu.
Wykonywanie prac przyspieszonych
Od wersji WorkManager 2.7 aplikacja może wywoływać metodę setExpedited()
, aby zadeklarować, że
zadanie WorkRequest
powinno być uruchamiane jak najszybciej za pomocą zadania przyspieszonego.
ten fragment kodu zawiera przykład użycia setExpedited()
:
Kotlin
val request = OneTimeWorkRequestBuilder<SyncWorker>() .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build() WorkManager.getInstance(context) .enqueue(request)
Java
OneTimeWorkRequest request = new OneTimeWorkRequestBuilder<T>() .setInputData(inputData) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .build();
W tym przykładzie inicjujemy wystąpienie OneTimeWorkRequest
i wywołujemy funkcję
setExpedited()
. To żądanie stanie się wówczas procesem przyspieszonym. Jeśli limit
zacznie działać od razu w tle. Jeśli limit ma
będzie używany, parametr OutOfQuotaPolicy
wskazuje, że żądanie powinno
przebiegać jak normalnie, bez przyspieszonego generowania.
Zgodność wsteczna i usługi na pierwszym planie
Aby zachować zgodność wsteczną na potrzeby przyspieszonego wykonywania zadań, WorkManager może uruchamiać usługi na pierwszym planie na platformach w wersjach starszych niż Android 12. Usługi działające na pierwszym planie mogą wyświetlać użytkownikowi powiadomienia.
Metody getForegroundInfoAsync()
i getForegroundInfo()
w instancji roboczej
włącz w WorkManageru wyświetlanie powiadomień, gdy zadzwonisz do: setExpedited()
przed Androidem 12.
Każdy element ListenableWorker
musi implementować metodę getForegroundInfo
, jeśli
prosi o uruchomienie zadania jako zadania przyspieszonego.
W przypadku kierowania na Androida 12 lub nowszego usługi działające na pierwszym planie pozostają dostępne dla:
za pomocą odpowiedniej metody setForeground
.
Instancja robocza
Pracownicy nie wiedzą, czy ich praca przebiega szybciej, czy nie. Ale
może wyświetlać powiadomienie w niektórych wersjach Androida, gdy
WorkRequest
została przyspieszona.
Aby to umożliwić, WorkManager udostępnia metodę getForegroundInfoAsync()
,
który musisz zaimplementować, aby usługa WorkManager mogła wyświetlać powiadomienie, by uruchomić
ForegroundService
.
Komponent roboczy Coroutine
Jeśli używasz metody CoroutineWorker
, musisz zaimplementować getForegroundInfo()
. Ty to
przekaż ją usłudze setForeground()
w ciągu doWork()
. Spowoduje to utworzenie
na urządzeniach z Androidem w wersji starszej niż 12.
Przyjrzyjmy się temu przykładowi:
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()
}
}
Zasady dotyczące limitów
Możesz określić, co ma się stać z pracą przyspieszoną, gdy aplikacja osiągnie
limit wykonywania. Aby kontynuować, możesz mijać setExpedited()
:
OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST
, który powoduje, że zadanie jak zwykłe żądanie pracy. Fragment kodu powyżej to potwierdza.OutOfQuotaPolicy.DROP_WORK_REQUEST
, co powoduje anulowanie żądania, jeśli nie ma wystarczającego limitu.
Przykładowa aplikacja
Pełny przykład wykorzystania przyspieszonej pracy w WorkManager 2.7.0 znajdziesz przy użyciu narzędzia WorkManagerSample na GitHubie.
Przyspieszona praca odroczona
System próbuje wykonać dane przyspieszone zadanie jak najszybciej po . Jednak, podobnie jak w przypadku innych rodzajów zadań, system może opóźnić rozpoczęcie nowych prac przyspieszonych, na przykład w następujących przypadkach:
- Obciążenie: zbyt duże obciążenie systemu, co może wystąpić, gdy zostanie przestawiony zbyt wiele zadań. już uruchomionych lub gdy w systemie jest za mało pamięci.
- Limit: limit przyspieszonego zadania został przekroczony. Praca przyspieszona wykorzystuje system limitów oparty na zasobnikach gotowości aplikacji i ogranicza maksymalny czas wykonywania w ruchomym oknie czasowym. Limity używane w: przyspieszonych czynności są bardziej restrykcyjne niż te używane w przypadku zadań w tle.
Planowanie zadań okresowych
Aplikacja może czasami wymagać okresowego wykonywania pewnych zadań. Przykład: warto od czasu do czasu tworzyć kopie zapasowe danych, pobierać nowe materiały i pobierać je lub przesyłanie dzienników na serwer.
Oto jak możesz użyć narzędzia PeriodicWorkRequest
do utworzenia
Obiekt WorkRequest
, który jest okresowo uruchamiany:
Kotlin
val saveRequest = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS) // Additional configuration .build()
Java
PeriodicWorkRequest saveRequest = new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS) // Constraints .build();
W tym przykładzie zadanie jest zaplanowane z godzinnym odstępem.
Okres interwału to minimalny czas między powtórzeniami. dokładny czas wykonania instancji roboczej zależy od ograniczeń których używasz w obiekcie WorkRequest i podanych optymalizacji. przez system.
Elastyczne interwały biegów
Jeśli charakter Twojej pracy sprawia, że zależy Ci na synchronizacji czasu, możesz skonfigurować
Twój PeriodicWorkRequest
, aby biegać elastycznie
okresu w każdym przedziale czasu, jak pokazano na rys. 1.
Rysunek 1. Diagram pokazuje powtarzające się interwały z okresem elastycznym w które można uruchomić.
Aby zdefiniować pracę okresową z okresem elastycznym, przekaż flexInterval
wraz z parametrem
repeatInterval
podczas tworzenia PeriodicWorkRequest
. Okres elastyczny
zaczyna się o repeatInterval - flexInterval
i kończy się na końcu interwału.
Oto przykład zadań okresowych, które mogą być wykonywane w ciągu ostatnich 15 lat min w każdej godzinie.
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();
Interwał powtarzania nie może być mniejszy niż
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS
i elastyczność
interwał musi być większy niż lub równy
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS
Wpływ ograniczeń na pracę okresową
Do prac okresowych możesz stosować ograniczenia. Możesz na przykład dodać
do żądania związanego z pracą, tak aby działała ona tylko wtedy, gdy
urządzenie się ładuje. W tym przypadku, nawet jeśli zdefiniowany interwał powtarzania minie,
PeriodicWorkRequest
nie będzie działać, dopóki ten warunek nie zostanie spełniony. Może to spowodować
opóźnienia konkretnego wykonania pracy lub nawet pominięcie go, jeśli
nie są spełnione warunki w przedziale uruchomienia.
Ograniczenia pracy
Ograniczenia powodują odroczenie zadań do momentu spełnienia optymalnych warunków. W usłudze WorkManager dostępne są poniższe ograniczenia.
Typ sieci | Ogranicza typ sieci wymagany do działania.
Na przykład Wi-Fi (UNMETERED ).
|
Niski poziom baterii | Jeśli zasada ma wartość Prawda, praca nie będzie wykonywana, gdy urządzenie będzie działać w trybie niskiego poziomu baterii. |
Wymaga ładowania | Jeśli ma wartość Prawda, Twoja praca będzie wykonywana tylko podczas ładowania urządzenia. |
Brak urządzenia | Jeśli zasada ma wartość Prawda, urządzenie użytkownika jest nieaktywne, aby można było uruchomić pracę. Jest to przydatne przy przeprowadzaniu operacji zbiorczych, które w przeciwnym razie mogłyby mieć negatywny wpływ na wydajność innych aplikacji aktywnych aktywnie na urządzeniu użytkownika. |
Mało miejsca na dane | Jeśli zasada ma wartość Prawda, pliki nie są uruchamiane, jeśli na urządzeniu użytkownika jest za mało miejsca. |
Aby utworzyć zbiór ograniczeń i powiązać go z jakąś pracą, utwórz
instancję Constraints
przy użyciu interfejsu Contraints.Builder()
i przypisz ją do
WorkRequest.Builder()
Na przykład ten kod tworzy żądanie robocze, które jest uruchamiane tylko wtedy, urządzenie użytkownika ładuje się i jest połączone z Wi-Fi:
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();
Jeśli określisz wiele ograniczeń, praca będzie wykonywana tylko wtedy, gdy wszystkie są spełnione ograniczenia.
Jeśli ograniczenie przestanie obowiązywać w trakcie pracy, WorkManager zatrzyma instancję roboczą. Zadanie zostanie ponowione, gdy wszystkie są spełnione ograniczenia.
Opóźniona praca
Jeśli praca nie ma ograniczeń lub wszystkie ograniczenia są po umieszczeniu zadania w kolejce system może je uruchomić natychmiast. Jeśli nie chcesz, aby zadanie było wykonywane natychmiast, możesz określić musisz zacząć pracę z minimalnym opóźnieniem.
Ten przykład pokazuje, jak ustawić czas pracy co najmniej 10 minut później został dodany do kolejki.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setInitialDelay(10, TimeUnit.MINUTES) .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .setInitialDelay(10, TimeUnit.MINUTES) .build();
Chociaż ten przykład pokazuje, jak ustawić początkowe opóźnienie dla
OneTimeWorkRequest
, możesz też ustawić początkowe opóźnienie dla
PeriodicWorkRequest
W takim przypadku tylko pierwsze uruchomienie zadania okresowego
miałoby miejsce z opóźnieniem.
Zasada ponawiania i wycofywania
Jeśli chcesz, aby usługa WorkManager ponownie wykonała zadanie, możesz zwrócić
Result.retry()
od Twojej instancji roboczej. W takim przypadku Twoja praca
został przełożony zgodnie z opóźnieniem wycofywania i zasadami wycofywania.
Opóźnienie wycofania określa minimalny czas oczekiwania przed ponowną próbą. za pierwszym razem. Ta wartość nie może być mniejsza niż 10 sekund (lub MIN_BACKOFF_MILLIS).
Zasada ponawiania określa, jak opóźnienie do ponowienia powinno się zwiększać w przypadku kolejnych próbach. WorkManager obsługuje 2 zasady wycofywania:
LINEAR
iEXPONENTIAL
Każde żądanie pracy ma zasadę ponowienia i opóźnienia. Zasada domyślna
jest EXPONENTIAL
(opóźnienie wynosi 30 sekund, ale możesz to zmienić w
konfiguracji żądania służbowego.
Oto przykład dostosowywania zasady opóźnienia ponowienia i zasady.
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .setBackoffCriteria( BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .setBackoffCriteria( BackoffPolicy.LINEAR, OneTimeWorkRequest.MIN_BACKOFF_MILLIS, TimeUnit.MILLISECONDS) .build();
W tym przykładzie minimalne opóźnienie do ponowienia jest ustawione na minimalną dopuszczalne wartości,
10 sekund. Ponieważ zasada ma wartość LINEAR
, interwał ponawiania prób zwiększy się o
około 10 sekund przy każdej nowej próbie. Na przykład pierwsze uruchomienie
za pomocą polecenia Result.retry()
zostanie ponowna próba nawiązania połączenia za 10 sekund,
następnie następnie 20, 30, 40 itd., jeśli zadanie będzie nadal zwracać
Result.retry()
po kolejnych próbach. Jeśli zasada ponawiania była ustawiona na
EXPONENTIAL
, sekwencja czasu trwania ponawiania będzie bliższa wartości 20, 40, 80 itd.
włącz.
Tag działa
Każde żądanie służbowe ma unikalny identyfikator, który umożliwia identyfikację które można wykonać później, aby anulować pracę lub obserwować jej postęp.
Jeśli masz grupę zadań powiązanych logicznie, przydatne może być również oznaczyć je tagami. Oznaczanie tagami pozwala pracować z grupą prac wszystkich żądań.
Na przykład WorkManager.cancelAllWorkByTag(String)
anuluje
wszystkie żądania robocze z określonym tagiem oraz
WorkManager.getWorkInfosByTag(String)
zwraca listę
Obiekty WorkInfo, których można używać do określania bieżącego stanu pracy.
Ten kod pokazuje, jak dodać „czyszczenie” dodaj tagi do swojej pracy:
Kotlin
val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>() .addTag("cleanup") .build()
Java
WorkRequest myWorkRequest = new OneTimeWorkRequest.Builder(MyWork.class) .addTag("cleanup") .build();
Do jednego żądania roboczego można dodać wiele tagów. Wewnętrznie te
są przechowywane jako zbiór ciągów znaków. Aby uzyskać zestaw tagów powiązanych z
w WorkRequest
możesz użyć WorkInfo.getTags().
Z klasy Worker
możesz pobrać zestaw tagów za pomocą
ListenableWorker.getTags().
Przypisz dane wejściowe
Twoja praca może wymagać danych wejściowych. Na przykład: uchwyty przesyłania obrazu mogą wymagać podania identyfikatora URI obrazu jako dane wejściowe.
Wartości wejściowe są przechowywane jako pary klucz-wartość w obiekcie Data
i można je ustawić
w zależności od zadania. WorkManager dostarczy dane wejściowe Data
do
podczas wykonywania pracy. Zajęcia w aplikacji Worker
mają dostęp
dla argumentów wejściowych przez wywołanie metody Worker.getInputData()
.
poniżej pokazuje, jak utworzyć instancję Worker
, która
wymaga danych wejściowych i sposobu ich przesyłania w żądaniu służbowym.
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();
Analogicznie klasy Data
można użyć do wygenerowania zwracanej wartości. Dane wejściowe
danych wyjściowych omówiono bardziej szczegółowo w sekcji Parametry wejściowe
zwracanych wartości.
Dalsze kroki
Na stronie Stany i obserwacja znajdziesz więcej informacji o stanach pracy i monitorowanie postępów.