Te ćwiczenia są częścią kursu Android Kotlin Fundamentals. Skorzystaj z tego kursu, jeśli będziesz wykonywać kolejno kilka ćwiczeń z programowania. Wszystkie ćwiczenia z kursu są wymienione na stronie docelowej ćwiczeń z programowania na temat Kotlin.
Wstęp
Większość rzeczywistych aplikacji wymaga wykonywania długotrwałych zadań w tle. Aplikacja może na przykład przesyłać pliki na serwer, synchronizować dane z serwera i zapisywać je w bazie danych Room
, wysyłać dzienniki na serwer oraz wykonywać kosztowne operacje na danych. Takie operacje należy wykonywać w tle, poza wątkiem interfejsu (główny wątek). Zadania w tle zużywają ograniczone zasoby urządzenia, takie jak pamięć RAM i bateria. Może to negatywnie wpłynąć na wrażenia użytkownika.
Z tego ćwiczenia dowiesz się, jak używać narzędzia WorkManager
, by planować zadania w tle w sposób zoptymalizowany i wydajny. Więcej informacji o innych rozwiązaniach umożliwiających przetwarzanie w tle znajdziesz w artykule Przewodnik po przetwarzaniu w tle.
Co musisz wiedzieć
- Używanie elementów
ViewModel
,LiveData
iRoom
komponentów architektury Androida. - Jak przeprowadzać przekształcenia w klasie
LiveData
. - Jak utworzyć i uruchomić program.
- Jak używać adapterów do wiązania danych.
- Jak wczytać dane z pamięci podręcznej za pomocą wzorca repozytorium.
Czego się nauczysz
- Jak utworzyć
Worker
, który reprezentuje jednostkę pracy. - Jak utworzyć
WorkRequest
, aby poprosić o wykonanie zadania. - Dowiedz się, jak dodać ograniczenia do
WorkRequest
, by określić sposób i czas działania instancji roboczej. - Jak używać
WorkManager
do planowania zadań w tle.
Jakie zadania wykonasz:
- Utwórz węzeł roboczy, aby wykonać zadanie w tle, aby wstępnie pobrać playlistę filmów DevBytes z sieci.
- Zaplanuj okresowe uruchamianie instancji roboczej.
- Dodaj ograniczenia do
WorkRequest
. - Zaplanuj okresowe przeprowadzanie
WorkRequest
w ciągu dnia.
W tym ćwiczeniu będziesz pracować nad aplikacją DevBytes utworzoną w poprzednim ćwiczeniu. (Jeśli nie masz tej aplikacji, możesz pobrać kod startowy lekcji).
Aplikacja DevBytes zawiera listę filmów w DevByte, czyli krótkich samouczków przygotowanych przez zespół Google Developers ds. relacji z deweloperami. Filmy zawierają funkcje dla programistów i sprawdzone metody dotyczące ich programowania.
Aby zwiększyć komfort użytkowników aplikacji, pobieraj filmy raz na dzień. Dzięki temu użytkownik ma dostęp do nowych treści zaraz po otwarciu aplikacji.
W tym zadaniu pobierzesz i przejrzysz kod startowy.
Krok 1. Pobierz i uruchom aplikację startową
Możesz dalej pracować w aplikacji DevBytes, która jest dostępna w Twoim poprzednim kursie z programowania (jeśli go masz). Możesz też pobrać aplikację startową.
W tym zadaniu pobierzesz i uruchomisz aplikację startową, a następnie sprawdzisz jej kod.
- Jeśli nie masz jeszcze aplikacji DevBytes, pobierz kod startowy DevBytes dla tego ćwiczenia z programowania z projektu DevBytesRepository z GitHuba.
- Rozpakuj kod i otwórz projekt w Android Studio.
- Połącz urządzenie testowe lub emulator z internetem, jeśli nie jest jeszcze połączony. Utwórz i uruchom aplikację. Ta aplikacja pobiera listę filmów DevByte z sieci i wyświetla je.
- W aplikacji kliknij dowolny film, aby otworzyć go w aplikacji YouTube.
Krok 2. Poznaj kod
Aplikacja ta zawiera wiele kodów wprowadzonych w poprzednim ćwiczeniu z programowania. Kod startowy tego ćwiczenia z programowania zawiera moduły sieciowe, interfejs, pamięć podręczną offline i repozytorium. Możesz zaplanować działanie zadania w tle przy użyciu WorkManager
.
- W Android Studio rozwiń wszystkie pakiety.
- Poznaj pakiet
database
Pakiet zawiera elementy bazy danych i lokalną bazę danych, która jest zaimplementowana za pomocą funkcjiRoom
. - Poznaj pakiet
repository
Pakiet zawiera klasęVideosRepository
, która wyodrębnia warstwę danych od reszty aplikacji. - Zapoznaj się z pozostałymi fragmentami kodu startowego samodzielnie i skorzystaj z wcześniejszego ćwiczenia z programowania.
WorkManager
jest jednym z komponentów architektury Androida i jest częścią pakietu Jetpack na Androida. WorkManager
oznacza prace w tle, które można odroczyć i wymagają gwarantowanego wykonania:
- Możliwe do odczytania oznacza, że zadanie nie musi być uruchamiane natychmiast. Na przykład wysyłanie danych analitycznych do serwera lub synchronizowanie bazy danych w tle może być opóźnione.
- Gwarantowane wykonanie oznacza, że zadanie będzie uruchamiane nawet po zamknięciu aplikacji lub ponownym uruchomieniu urządzenia.
WorkManager
uruchamia prace w tle, ale rozwiązuje problemy ze zgodnością i sprawdzone metody dotyczące kondycji baterii i systemu. WorkManager
zapewnia zgodność z interfejsem API na poziomie 14. WorkManager
wybiera odpowiedni sposób planowania zadania w tle w zależności od poziomu interfejsu API urządzenia. Może korzystać z metody JobScheduler
(interfejs API 23 i nowsze) lub kombinacji funkcji AlarmManager
i BroadcastReceiver
.
WorkManager
umożliwia też określenie kryteriów uruchamiania zadania w tle. Może być na przykład konieczne, aby zadanie działało tylko wtedy, gdy stan baterii, stan sieci lub stan ładowania spełniają określone kryteria. W dalszej części tego ćwiczenia dowiesz się, jak określać ograniczenia.
W tym ćwiczeniu zaplanujesz zadanie pobierania raz dziennie playlisty wideo DevBytes z sieci. Aby zaplanować to zadanie, użyj biblioteki WorkManager
.
- Otwórz plik
build.gradle (Module:app)
i dodaj zależnośćWorkManager
do projektu.
Jeśli używasz najnowszej wersji biblioteki, aplikacja z rozwiązaniami powinna skompilować się w oczekiwany sposób. Jeśli tak się nie stanie, spróbuj rozwiązać problem lub przywrócić wersję biblioteki widoczną poniżej.
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"
- Zsynchronizuj swój projekt i upewnij się, że nie ma w nim błędów kompilacji.
Zanim dodasz kod do projektu, zapoznaj się z tymi zajęciami w bibliotece WorkManager
:
Worker
Na tych zajęciach definiujesz rzeczywiste zadania (zadanie), które mają być wykonywane w tle. Wydłużasz tę klasę i zastępujesz metodędoWork()
. MetodadoWork()
to kod, który umieszczasz w tle, aby np. synchronizować dane z serwerem lub przetwarzać obrazy. W tym zadaniu stosujeszWorker
.WorkRequest
Ta klasa reprezentuje żądanie uruchomienia instancji roboczej w tle. Użyj metodyWorkRequest
, aby skonfigurować sposób i czas wykonywania zadania, korzystając zConstraints
, na przykład podłączonego urządzenia lub podłączonego do Wi-Fi. Implementację funkcjiWorkRequest
przeprowadzasz w późniejszym zadaniu.WorkManager
Te zajęcia będą zaplanowane i zaplanowane naWorkRequest
.WorkManager
planuje zadania w sposób, który rozkłada obciążenie zasobów systemowych i jednocześnie spełnia określone przez Ciebie ograniczenia. Implementację funkcjiWorkManager
przeprowadzasz w późniejszym zadaniu.
Krok 1. Utwórz węzeł roboczy
W tym zadaniu dodasz Worker
, aby pobierać w tle tło playlisty DevBytes.
- W pakiecie
devbyteviewer
utwórz nowy pakiet o nazwiework
. - W pakiecie
work
utwórz nową klasę Kotlin o nazwieRefreshDataWorker
. - Wydłuż klasę
RefreshDataWorker
z klasyCoroutineWorker
. Przekażcontext
iWorkerParameters
jako parametry konstruktora.
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
}
- Aby naprawić błąd abstrakcyjnej klasy, zastąp metodę
doWork()
w klasieRefreshDataWorker
.
override suspend fun doWork(): Result {
return Result.success()
}
Funkcja zawieszenia to funkcja, którą można wstrzymać i wznowić później. Zawieszona funkcja może wykonać długo trwające działanie i poczekać na zakończenie operacji bez blokowania głównego wątku.
Krok 2. Zaimplementuj dowork()
Metoda doWork()
wewnątrz klasy Worker
jest wywoływana w wątku w tle. Ta metoda działa synchronicznie i zwraca obiekt ListenableWorker.Result
. System Android daje Worker
maksymalnie 10 minut na dokończenie wykonania i zwrócenie obiektu ListenableWorker.Result
. Po upływie tego czasu system wymusza zatrzymanie Worker
.
Aby utworzyć obiekt ListenableWorker.Result
, wywołaj jedną z tych metod statycznych, by wskazać stan ukończenia zadania w tle:
Result.success()
– udało się ukończyć zadanie.Result.failure()
– zadanie zostało trwale wykonane.Result.retry()
– przejściowa awaria, którą należy wykonać ponownie.
W tym zadaniu implementujesz metodę doWork()
, która służy do pobierania playlisty wideo DevBytes z sieci. Aby pobrać dane z sieci, możesz ponownie użyć istniejących metod z klasy VideosRepository
.
- W klasie
RefreshDataWorker
wewnątrz obiektudoWork()
utwórz i utwórz instancję obiektuVideosDatabase
i obiektuVideosRepository
.
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
return Result.success()
}
- W klasie
RefreshDataWorker
wewnątrz tagudoWork()
, nad instrukcjąreturn
wywołaj metodęrefreshVideos()
wewnątrz blokutry
. Dodaj dziennik do śledzenia uruchomionej instancji roboczej.
try {
repository.refreshVideos( )
Timber.d("Work request for sync is run")
} catch (e: HttpException) {
return Result.retry()
}
Aby naprawić błąd &"Nierozwiązany problem z plikiem referencyjnym, zaimportuj retrofit2.HttpException
.
- Oto pełna klasa
RefreshDataWorker
:
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
try {
repository.refreshVideos()
} catch (e: HttpException) {
return Result.retry()
}
return Result.success()
}
}
Worker
określa jednostkę pracy, a WorkRequest
określa sposób i czas uruchamiania zadania. Są 2 konkretne implementacje klasy WorkRequest
:
- Klasa
OneTimeWorkRequest
służy do jednorazowych zadań. Zadanie jednorazowe ma miejsce tylko raz. - Klasa
PeriodicWorkRequest
dotyczy zadań cyklicznych, które powtarzają się w określonych odstępach czasu.
Zadania mogą być jednorazowe lub okresowe, więc wybierz odpowiednie zajęcia. Więcej informacji o harmonogramie zadań cyklicznych znajdziesz w dokumentacji zadań cyklicznych.
W tym zadaniu definiujesz i uruchamiasz uruchomienie WorkRequest
instancji roboczej utworzonej w poprzednim zadaniu.
Krok 1. Skonfiguruj zadanie cykliczne
Klasa Application
w aplikacji na Androida to klasa podstawowa zawierająca wszystkie inne komponenty, takie jak aktywności i usługi. Gdy zostanie utworzony proces aplikacji lub pakietu, klasa Application
(lub dowolna podklasa Application
) jest tworzona przed innymi klasami.
W przykładowej aplikacji klasa DevByteApplication
jest podklasą klasy Application
. Klasa DevByteApplication
to dobre miejsce na zaplanowanie spotkania WorkManager
.
- W klasie
DevByteApplication
utwórz metodę o nazwiesetupRecurringWork()
, aby skonfigurować zadanie cykliczne w tle.
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
}
- W ramach metody
setupRecurringWork()
utwórz i zainicjuj okresowe żądanie zadania do uruchomienia raz dziennie, korzystając z metodyPeriodicWorkRequestBuilder()
. Przekaż klasęRefreshDataWorker
utworzoną w poprzednim zadaniu. Powtarzaj przedział czasu1
za pomocą jednostki czasuTimeUnit.
DAYS
.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
Aby naprawić ten błąd, zaimportuj java.util.concurrent.TimeUnit
.
Krok 2. Zaplanuj żądanie w WorkManager
Po zdefiniowaniu elementu WorkRequest
możesz go zaplanować za pomocą metody WorkManager
, korzystając z metody enqueueUniquePeriodicWork()
. Ta metoda pozwala dodać do kolejki unikalną nazwę PeriodicWorkRequest
, w której tylko 1 element PeriodicWorkRequest
o określonej nazwie może być aktywny.
Możesz na przykład chcieć, aby tylko jedna operacja synchronizacji była aktywna. Jeśli jakaś operacja synchronizacji oczekuje na uruchomienie, możesz ją uruchomić lub zastąpić nową, korzystając z zasady IstniejącyPeriodicWorkPolicy.
Więcej informacji o tym, jak zaplanować publikację WorkRequest
, znajdziesz w dokumentacji WorkManager
.
- Na początku klasy
RefreshDataWorker
dodaj obiekt towarzyszący. Zdefiniuj nazwę zadania, aby jednoznacznie zidentyfikować tego pracownika.
companion object {
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
- Na zajęciach w
DevByteApplication
zaplanuj zadanie za pomocą metodyenqueueUniquePeriodicWork()
na końcu metodysetupRecurringWork()
. Przekazano wyliczenieKEEP
klasy IstniejącePeriodicWorkPolicy. PrzekażrepeatingRequest
jako parametrPeriodicWorkRequest
.
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
Jeśli istnieją zadania oczekujące (nieukończone), które mają taką samą nazwę, parametr ExistingPeriodicWorkPolicy.
KEEP
sprawia, że element WorkManager
zachowuje poprzednią aktywność cykliczną i odrzuca nowe zadanie.
- Na początku klasy
DevByteApplication
utwórz obiektCoroutineScope
. Przekaż do elementuDispatchers.Default
jako parametr konstruktora.
private val applicationScope = CoroutineScope(Dispatchers.Default)
- W klasie
DevByteApplication
dodaj nową metodę o nazwiedelayedInit()
, aby rozpocząć współpracę.
private fun delayedInit() {
applicationScope.launch {
}
}
- Wywołaj metodę
delayedInit()
z wywołaniemsetupRecurringWork()
. - Przenieś inicjowanie drewna z metody
onCreate()
do metodydelayedInit()
.
private fun delayedInit() {
applicationScope.launch {
Timber.plant(Timber.DebugTree())
setupRecurringWork()
}
}
- W klasie
DevByteApplication
na końcu metodyonCreate()
dodaj wywołanie metodydelayedInit()
.
override fun onCreate() {
super.onCreate()
delayedInit()
}
- Otwórz panel Logcat na dole okna Android Studio. Filtruj według:
RefreshDataWorker
. - Uruchom aplikację.
WorkManager
natychmiast planuje zadanie cykliczne.
W panelu Logcat znajdź informacje o dzienniku, które pokazują, że żądanie zadania jest zaplanowane, a następnie je uruchomisz.
D/RefreshDataWorker: Work request for sync is run I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
Dziennik WM-WorkerWrapper
jest wyświetlany w bibliotece WorkManager
, więc nie można go zmienić.
Krok 3. (Opcjonalnie) Zaplanuj WorkWork na minimalny okres
W tym kroku skracasz przedział czasu z 1 do 15 minut. W ten sposób możesz zobaczyć logi okresowego żądania pracy w działaniu.
- W klasie
DevByteApplication
w metodziesetupRecurringWork()
skomentuj bieżącą definicjęrepeatingRequest
. Dodaj nowe zadanie służbowe z odstępem powtarzanym co15
min.
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.build()
- Otwórz panel Logcat w Android Studio i użyj filtra
RefreshDataWorker
. Aby wyczyścić poprzednie dzienniki, kliknij ikonę Wyczyść dziennik. - Uruchom aplikację, a
WorkManager
natychmiast zaplanuje zadanie cykliczne. W panelu Logcat zwróć uwagę na logi – żądanie pracy jest wykonywane co 15 minut. Zaczekaj 15 minut, aby zobaczyć inny zestaw dzienników żądań pracy. Nie zamykaj aplikacji ani nie zamykaj jej. Menedżer pracy powinien nadal działać.
Pamiętaj, że odstęp między czasem nie przekracza 15 minut, a czasami nawet ponad 15 minut. Dokładny czas wykorzystania zależy od optymalizacji baterii systemu operacyjnego.
12:44:40 D/RefreshDataWorker: Work request for sync is run 12:44:40 I/WM-WorkerWrapper: Worker result SUCCESS for Work 12:59:24 D/RefreshDataWorker: Work request for sync is run 12:59:24 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:15:03 D/RefreshDataWorker: Work request for sync is run 13:15:03 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:29:22 D/RefreshDataWorker: Work request for sync is run 13:29:22 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:44:26 D/RefreshDataWorker: Work request for sync is run 13:44:26 I/WM-WorkerWrapper: Worker result SUCCESS for Work
Gratulacje! Instancja robocza została utworzona i zaplanowana do wysłania przez WorkManager
. Pojawił się jednak problem: nie określono żadnych ograniczeń. WorkManager
zaplanuje pracę raz dziennie, nawet jeśli bateria urządzenia jest słaba, nie śpisz lub nie ma połączenia z siecią. Zmniejszy to wydajność baterii i wydajność urządzenia, co może pogorszyć wygodę użytkowników.
W kolejnym zadaniu rozwiążesz ten problem, dodając ograniczenia.
W poprzednim zadaniu zaplanowano prośbę o wykonanie zadania: WorkManager
. W tym zadaniu dodasz kryteria określające czas wykonania zadania.
Podczas definiowania właściwości WorkRequest
możesz określić ograniczenia dotyczące czasu uruchamiania obiektu Worker
. Możesz na przykład określić, że działanie ma być uruchamiane tylko wtedy, gdy urządzenie jest bezczynne lub podłączone do zasilania i połączone z Wi-Fi. Możesz też określić zasady działania ponowienia próby. Obsługiwane ograniczenia to metody ustawione w Constraints.Builder
. Więcej informacji znajdziesz w artykule Definiowanie zadań służbowych.
Krok 1. Dodaj obiekt ograniczeń i ustaw jedno ograniczenie
W tym kroku utworzysz obiekt Constraints
i ustawisz dla niego jedno ograniczenie, czyli typ sieci. Łatwiej zauważyć logi za pomocą tylko jednego ograniczenia. W późniejszym kroku dodaj inne ograniczenia).
- W klasie
DevByteApplication
na początku elementusetupRecurringWork()
zdefiniujval
typuConstraints
. Użyj metodyConstraints.Builder()
.
val constraints = Constraints.Builder()
Aby naprawić ten błąd, zaimportuj androidx.work.Constraints
.
- Użyj metody
setRequiredNetworkType()
, aby dodać ograniczenie typu sieci do obiektuconstraints
. Użyj wyliczeniaUNMETERED
, aby zadanie zostało uruchomione tylko wtedy, gdy urządzenie jest w sieci bez pomiaru.
.setRequiredNetworkType(NetworkType.UNMETERED)
- Aby wygenerować ograniczenia w konstruktorze, użyj metody
build()
.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
Teraz musisz ustawić nowo utworzony obiekt Constraints
w żądaniu roboczym.
- W klasie
DevByteApplication
w metodziesetupRecurringWork()
ustaw obiektConstraints
na okresowe żądanie pracyrepeatingRequest
. Aby ustawić ograniczenia, dodaj metodęsetConstraints()
nad wywołaniem metodybuild()
.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build()
Krok 2. Uruchom aplikację i sprawdź dzienniki
W tym kroku uruchomisz aplikację i zauważysz, że objęte nim żądanie pracy jest uruchamiane w tle w określonych odstępach czasu.
- Odinstaluj aplikację z urządzenia lub emulatora, aby anulować wcześniej zaplanowane zadania.
- Otwórz panel Logcat w Android Studio. W panelu Logcat wyczyść poprzednie logi, klikając ikonę Wyczyść dziennik
po lewej stronie. Filtruj według:
work
. - Wyłącz Wi-Fi w urządzeniu lub emulatorze, aby sprawdzić, jak działają ograniczenia. Bieżący kod ustawia tylko jedno ograniczenie, co oznacza, że żądanie powinno być wykonywane tylko w sieci bez pomiaru. Ponieważ Wi-Fi jest wyłączone, urządzenie nie jest połączone z siecią, z pomiarem użycia danych ani bez pomiaru. To ograniczenie nie zostanie spełnione.
- Uruchom aplikację i zobacz panel Logcat.
WorkManager
natychmiast planuje zadanie w tle. Zadanie nie jest spełnione, ponieważ zadanie nie jest uruchomione.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
- Włącz Wi-Fi w urządzeniu lub emulatorze i obejrzyj panel Logcat. Teraz zaplanowane zadanie w tle jest uruchamiane mniej więcej co 15 minut, o ile limit sieci jest spełniony.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled 11:31:47 D/RefreshDataWorker: Work request for sync is run 11:31:47 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 11:46:45 D/RefreshDataWorker: Work request for sync is run 11:46:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:03:05 D/RefreshDataWorker: Work request for sync is run 12:03:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:16:45 D/RefreshDataWorker: Work request for sync is run 12:16:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:31:45 D/RefreshDataWorker: Work request for sync is run 12:31:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:47:05 D/RefreshDataWorker: Work request for sync is run 12:47:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 13:01:45 D/RefreshDataWorker: Work request for sync is run 13:01:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
Krok 3. Dodaj więcej ograniczeń
W tym kroku dodasz do ograniczenia PeriodicWorkRequest
następujące ograniczenia:
- Bateria jest słaba.
- Ładowanie urządzenia.
- Urządzenie nieaktywne, dostępne tylko na poziomie API 23 (Android M) lub nowszym.
Zaimplementuj to w klasie DevByteApplication
.
- W klasie
DevByteApplication
wewnątrz metodysetupRecurringWork()
określ, że żądanie pracy powinno być uruchamiane tylko wtedy, gdy bateria jest słaba. Dodaj ograniczenie przed wywołaniem metodybuild()
i użyj metodysetRequiresBatteryNotLow()
.
.setRequiresBatteryNotLow(true)
- Zaktualizuj żądanie, by było ono aktywne tylko podczas ładowania urządzenia. Dodaj ograniczenie przed wywołaniem metody
build()
i użyj metodysetRequiresCharging()
.
.setRequiresCharging(true)
- Zaktualizuj żądanie, aby działało tylko wtedy, gdy urządzenie jest nieaktywne. Dodaj ograniczenie przed wywołaniem metody
build()
i użyj metodysetRequiresDeviceIdle()
. To ograniczenie działa wtedy, gdy użytkownik nie korzysta aktywnie z urządzenia. Ta funkcja jest dostępna tylko na urządzeniach z Androidem 6.0 (Marshmallow) lub nowszym, dodaj więc warunek do pakietu SDK w wersjiM
lub nowszej.
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
Oto pełna definicja obiektu constraints
.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()
- W ramach metody
setupRecurringWork()
zmień interwał żądania na jeden raz dziennie.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
Oto pełna implementacja metody setupRecurringWork()
z dziennikiem, która ułatwia śledzenie zaplanowanego czasu wykonywania zadania.
private fun setupRecurringWork() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
Timber.d("Periodic Work request for sync is scheduled")
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
}
- Aby usunąć zaplanowane wcześniej żądanie pracy, odinstaluj aplikację DevBytes z urządzenia lub emulatora.
- Uruchom aplikację, a
WorkManager
od razu zaplanuje wysłanie żądania służbowego. Żądanie działa raz dziennie, gdy są spełnione wszystkie ograniczenia. - To żądanie będzie działać w tle, dopóki aplikacja jest zainstalowana, nawet jeśli nie jest uruchomiona. Z tego powodu należy odinstalować aplikację z telefonu.
Brawo! Masz zaplanowaną i zaplanowaną prośbę o baterię do codziennego pobierania filmów z wyprzedzeniem w aplikacji DevBytes. WorkManager
planuje i uruchamia zadania, optymalizując zasoby systemowe. Twoi użytkownicy i ich baterie będą bardzo zadowoleni.
Projekt na Android Studio: DevBytesWorkManager.
- Interfejs API
WorkManager
ułatwia planowanie odroczonych zadań asynchronicznych, które muszą być uruchamiane niezawodnie. - Większość rzeczywistych aplikacji wymaga wykonywania długotrwałych zadań w tle. Aby zaplanować takie zadanie w sposób efektywny i wydajny, skorzystaj z
WorkManager
. - Główne klasy biblioteki w
WorkManager
toWorker
,WorkRequest
iWorkManager
. - Klasa
Worker
reprezentuje jednostkę pracy. Aby wdrożyć zadanie w tle, rozwiń klasęWorker
i zastąp metodędoWork()
. - Klasa
WorkRequest
reprezentuje żądanie wykonania jednostki pracy.WorkRequest
to klasa podstawowa do określania parametrów zadań zaplanowanych naWorkManager
. - Dostępne są 2 konkretne implementacje klasy
WorkRequest
:OneTimeWorkRequest
w przypadku jednorazowych zadań iPeriodicWorkRequest
w przypadku okresowych żądań pracy. - Podczas definiowania właściwości
WorkRequest
możesz określić wartośćConstraints
, która wskazuje, kiedyWorker
ma być uruchamiany. Ograniczenia dotyczą między innymi tego, czy urządzenie jest podłączone, nieaktywne czy połączone z Wi-Fi. - Aby dodać ograniczenia do obiektu
WorkRequest
, użyj metod opisanych w dokumentacjiConstraints.Builder
. Aby na przykład wskazać, żeWorkRequest
nie ma być uruchamiany, gdy bateria urządzenia jest słaba, użyj metodysetRequiresBatteryNotLow()
. - Po zdefiniowaniu zadania
WorkRequest
przekaż zadanie do systemu Android. Aby to zrobić, zaplanuj zadanie za pomocą jednej zWorkManager
metodenqueue
. - Dokładny czas wykonania funkcji
Worker
zależy od ograniczeń używanych wWorkRequest
i optymalizacji systemu.WorkManager
powstał z myślą o tych ograniczeniach, by zapewnić użytkownikom jak najlepsze działanie.
Kurs Udacity:
Dokumentacja dla programistów Androida:
- Definiowanie zadań służbowych
WorkManager
- Pierwsze kroki z WorkManagerem
- Zadania cykliczne
- Przewodnik po przetwarzaniu w tle
Inne:
Ta sekcja zawiera listę możliwych zadań domowych dla uczniów, którzy pracują w ramach tego ćwiczenia w ramach kursu prowadzonego przez nauczyciela. To nauczyciel może wykonać te czynności:
- W razie potrzeby przypisz zadanie domowe.
- Poinformuj uczniów, jak przesyłać zadania domowe.
- Oceń projekty domowe.
Nauczyciele mogą wykorzystać te sugestie tak długo, jak chcą lub chcą, i mogą przypisać dowolne zadanie domowe.
Jeśli samodzielnie wykonujesz te ćwiczenia z programowania, możesz sprawdzić swoją wiedzę w tych zadaniach domowych.
Pytanie 1
Jakie są konkretne implementacje klasy WorkRequest
?
▢ OneTimeWorkPeriodicRequest
▢ OneTimeWorkRequest
i PeriodicWorkRequest
▢ OneTimeWorkRequest
i RecurringWorkRequest
▢ OneTimeOffWorkRequest
i RecurringWorkRequest
Pytanie 2
Z których z poniższych klas korzysta WorkManager
, aby zaplanować zadanie działające w tle w interfejsie API 23 lub nowszym?
▢ Tylko JobScheduler
▢ BroadcastReceiver
i AlarmManager
▢ AlarmManager
i JobScheduler
▢ Scheduler
i BroadcastReceiver
Pytanie 3
Za pomocą którego interfejsu API dodajesz ograniczenia do interfejsu WorkRequest
?
▢ setConstraints()
▢ addConstraints()
▢ setConstraint()
▢ addConstraintsToWorkRequest()
Przejdź do następnej lekcji:
Linki do innych ćwiczeń z programowania w tym kursie znajdziesz na stronie docelowej z ćwiczeniami z podstaw Androida Kotlin.