Dieses Codelab ist Teil des Kurses „Grundlagen von Android und Kotlin“. Sie können diesen Kurs am besten nutzen, wenn Sie die Codelabs der Reihe nach durcharbeiten. Alle Codelabs des Kurses sind auf der Landingpage für Codelabs zu den Grundlagen von Android und Kotlin aufgeführt.
Einführung
Die meisten Apps in der Praxis müssen lang andauernde Hintergrundaufgaben ausführen. Eine App kann beispielsweise Dateien auf einen Server hochladen, Daten von einem Server synchronisieren und in einer Room-Datenbank speichern, Protokolle an einen Server senden oder rechenintensive Vorgänge für Daten ausführen. Solche Vorgänge sollten im Hintergrund und nicht im UI-Thread (Hauptthread) ausgeführt werden. Hintergrundaufgaben verbrauchen die begrenzten Ressourcen eines Geräts, z. B. RAM und Akku. Wenn dies nicht richtig gehandhabt wird, kann es zu einer schlechten Nutzererfahrung kommen.
In diesem Codelab erfahren Sie, wie Sie mit WorkManager eine Hintergrundaufgabe auf optimierte und effiziente Weise planen. Weitere Informationen zu anderen verfügbaren Lösungen für die Hintergrundverarbeitung in Android finden Sie im Leitfaden zur Hintergrundverarbeitung.
Was Sie bereits wissen sollten
- Verwendung der Android Architecture Components
ViewModel,LiveDataundRoom. - Transformationen für eine
LiveData-Klasse durchführen - Coroutine erstellen und starten
- Binding-Adapter in der Datenbindung verwenden
- So laden Sie Daten aus dem Cache mithilfe eines Repository-Musters.
Lerninhalte
- So erstellen Sie ein
Worker, das eine Arbeitseinheit darstellt. - So erstellen Sie eine
WorkRequest, um die Ausführung einer Aufgabe anzufordern. - Wie Sie Einschränkungen zum
WorkRequesthinzufügen, um zu definieren, wie und wann ein Worker ausgeführt werden soll. WorkManagerzum Planen von Hintergrundaufgaben verwenden
Aufgaben
- Erstelle einen Worker, um eine Hintergrundaufgabe auszuführen, mit der die DevBytes-Videoplaylist aus dem Netzwerk vorab abgerufen wird.
- Planen Sie die regelmäßige Ausführung des Workers.
- Fügen Sie dem
WorkRequestEinschränkungen hinzu. - Planen Sie eine regelmäßige
WorkRequest, die einmal täglich ausgeführt wird.
In diesem Codelab arbeiten Sie an der DevBytes-App, die Sie in einem vorherigen Codelab entwickelt haben. Wenn Sie diese App nicht haben, können Sie den Startercode für diese Lektion herunterladen.
In der DevBytes App wird eine Liste von DevByte-Videos angezeigt. Das sind kurze Tutorials, die vom Google Android Developer Relations-Team erstellt wurden. In den Videos werden Entwicklerfunktionen und Best Practices für die Android-Entwicklung vorgestellt.
Sie verbessern die Nutzerfreundlichkeit der App, indem Sie die Videos einmal täglich vorab abrufen. So erhalten Nutzer frische Inhalte, sobald sie die App öffnen.

In dieser Aufgabe laden Sie den Starter-Code herunter und sehen ihn sich an.
Schritt 1: Start-App herunterladen und ausführen
Sie können mit der DevBytes-App weiterarbeiten, die Sie im vorherigen Codelab erstellt haben (falls Sie sie haben). Alternativ können Sie die Starter-App herunterladen.
In dieser Aufgabe laden Sie die Starter-App herunter, führen sie aus und sehen sich den Starter-Code an.
- Wenn Sie die DevBytes-App noch nicht haben, laden Sie den DevBytes-Startcode für dieses Codelab aus dem DevBytesRepository-Projekt auf GitHub herunter.
- Entpacken Sie den Code und öffnen Sie das Projekt in Android Studio.
- Verbinden Sie Ihr Testgerät oder Ihren Emulator mit dem Internet, falls es noch nicht verbunden ist. Erstellen Sie die App und führen Sie sie aus. Die App ruft die Liste der DevByte-Videos aus dem Netzwerk ab und zeigt sie an.
- Tippe in der App auf ein beliebiges Video, um es in der YouTube App zu öffnen.
Schritt 2: Code ansehen
Die Starter-App enthält viel Code, der im vorherigen Codelab eingeführt wurde. Der Startercode für dieses Codelab enthält Netzwerk-, Benutzeroberflächen-, Offlinecache- und Repository-Module. Sie können sich auf die Planung der Hintergrundaufgabe mit WorkManager konzentrieren.
- Maximieren Sie in Android Studio alle Pakete.
- Sehen Sie sich das Paket
databasean. Das Paket enthält die Datenbankentitäten und die lokale Datenbank, die mitRoomimplementiert wird. - Sehen Sie sich das Paket
repositoryan. Das Paket enthält die KlasseVideosRepository, die die Datenschicht vom Rest der App abstrahiert. - Sehen Sie sich den restlichen Startcode selbst an. Das vorherige Codelab kann Ihnen dabei helfen.
WorkManager ist eine der Android-Architekturkomponenten und Teil von Android Jetpack. WorkManager ist für Hintergrundaufgaben, die aufgeschoben werden können und garantiert ausgeführt werden müssen:
- Aufschiebbar bedeutet, dass die Arbeit nicht sofort ausgeführt werden muss. Das Senden von Analysedaten an den Server oder das Synchronisieren der Datenbank im Hintergrund kann beispielsweise auf später verschoben werden.
- Garantierte Ausführung bedeutet, dass die Aufgabe auch dann ausgeführt wird, wenn die App beendet wird oder das Gerät neu startet.

Während WorkManager Hintergrundaufgaben ausführt, werden Kompatibilitätsprobleme und Best Practices für den Akku- und Systemzustand berücksichtigt. WorkManager ist ab API-Level 14 kompatibel. WorkManager wählt je nach API-Level des Geräts eine geeignete Methode zum Planen einer Hintergrundaufgabe aus. Dazu kann JobScheduler (bei API 23 und höher) oder eine Kombination aus AlarmManager und BroadcastReceiver verwendet werden.
Mit WorkManager können Sie auch Kriterien für die Ausführung der Hintergrundaufgabe festlegen. Sie möchten beispielsweise, dass die Aufgabe nur ausgeführt wird, wenn der Akkustatus, der Netzwerkstatus oder der Ladestatus bestimmte Kriterien erfüllt. Wie Sie Einschränkungen festlegen, erfahren Sie später in diesem Codelab.
In diesem Codelab planen Sie einen Task, um die DevBytes-Videoplaylist einmal täglich aus dem Netzwerk vorab abzurufen. Zum Planen dieser Aufgabe verwenden Sie die WorkManager-Bibliothek.
- Öffnen Sie die Datei
build.gradle (Module:app)und fügen Sie dem Projekt dieWorkManager-Abhängigkeit hinzu.
Wenn Sie die neueste Version der Bibliothek verwenden, sollte die Lösungs-App wie erwartet kompiliert werden. Wenn nicht, versuchen Sie, das Problem zu beheben, oder kehren Sie zur unten gezeigten Bibliotheksversion zurück.
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"- Synchronisieren Sie Ihr Projekt und prüfen Sie, ob Kompilierungsfehler auftreten.
Bevor Sie dem Projekt Code hinzufügen, sollten Sie sich mit den folgenden Klassen in der WorkManager-Bibliothek vertraut machen:
Worker
In dieser Klasse definieren Sie die eigentliche Arbeit (die Aufgabe), die im Hintergrund ausgeführt werden soll. Sie erweitern diese Klasse und überschreiben die MethodedoWork(). In der MethodedoWork()wird Code platziert, der im Hintergrund ausgeführt werden soll, z. B. zum Synchronisieren von Daten mit dem Server oder zum Verarbeiten von Bildern. In dieser Aufgabe implementieren Sie dieWorker.WorkRequest
Diese Klasse stellt eine Anfrage zum Ausführen des Workers im Hintergrund dar. MitWorkRequestkönnen Sie konfigurieren, wie und wann die Worker-Aufgabe ausgeführt werden soll. Dabei können SieConstraintswie „Gerät angeschlossen“ oder „WLAN-Verbindung“ verwenden. Sie implementieren dieWorkRequestin einer späteren Aufgabe.WorkManager
In dieser Klasse wird IhrWorkRequestgeplant und ausgeführt.WorkManagerplant Arbeitsanfragen so, dass die Last auf Systemressourcen verteilt wird und die von Ihnen angegebenen Einschränkungen berücksichtigt werden. Sie implementieren dieWorkManagerin einer späteren Aufgabe.
Schritt 1: Worker erstellen
In dieser Aufgabe fügen Sie ein Worker hinzu, um die DevBytes-Videoplaylist im Hintergrund vorab abzurufen.
- Erstellen Sie im Paket
devbyteviewerein neues Paket mit dem Namenwork. - Erstellen Sie im Paket
workeine neue Kotlin-Klasse mit dem NamenRefreshDataWorker. - Erweitern Sie die Klasse
RefreshDataWorkeraus der KlasseCoroutineWorker. Übergeben SiecontextundWorkerParametersals Konstruktorparameter.
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
}- Um den Fehler mit der abstrakten Klasse zu beheben, überschreiben Sie die Methode
doWork()in der KlasseRefreshDataWorker.
override suspend fun doWork(): Result {
return Result.success()
}Eine unterbrechbare Funktion ist eine Funktion, die pausiert und später fortgesetzt werden kann. Eine unterbrechbare Funktion kann einen lang andauernden Vorgang ausführen und darauf warten, dass er abgeschlossen wird, ohne den Hauptthread zu blockieren.
Schritt 2: doWork() implementieren
Die Methode doWork() in der Klasse Worker wird in einem Hintergrundthread aufgerufen. Die Methode wird synchron ausgeführt und sollte ein ListenableWorker.Result-Objekt zurückgeben. Das Android-System gibt einem Worker maximal 10 Minuten Zeit, um die Ausführung abzuschließen und ein ListenableWorker.Result-Objekt zurückzugeben. Nach Ablauf dieser Zeit wird die Worker vom System beendet.
Rufen Sie zum Erstellen eines ListenableWorker.Result-Objekts eine der folgenden statischen Methoden auf, um den Abschlussstatus der Hintergrundarbeit anzugeben:
Result.success(): Die Arbeit wurde erfolgreich abgeschlossen.Result.failure(): Die Arbeit wurde mit einem permanenten Fehler abgeschlossen.Result.retry(): Bei der Arbeit ist ein vorübergehender Fehler aufgetreten. Sie sollte wiederholt werden.
In dieser Aufgabe implementieren Sie die Methode doWork(), um die DevBytes-Videoplaylist aus dem Netzwerk abzurufen. Sie können die vorhandenen Methoden in der Klasse VideosRepository wiederverwenden, um die Daten aus dem Netzwerk abzurufen.
- Erstellen und instanziieren Sie in der Klasse
RefreshDataWorkerinnerhalb vondoWork()einVideosDatabase-Objekt und einVideosRepository-Objekt.
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
return Result.success()
}- Rufen Sie in der Klasse
RefreshDataWorkerinnerhalb vondoWork()über derreturn-Anweisung die MethoderefreshVideos()in einemtry-Block auf. Fügen Sie ein Log hinzu, um zu verfolgen, wann der Worker ausgeführt wird.
try {
repository.refreshVideos( )
Timber.d("Work request for sync is run")
} catch (e: HttpException) {
return Result.retry()
}Um den Fehler „Nicht aufgelöste Referenz“ zu beheben, importieren Sie retrofit2.HttpException.
- Hier finden Sie die vollständige
RefreshDataWorker-Klasse:
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()
}
}Eine Worker definiert eine Arbeitseinheit und mit dem WorkRequest wird festgelegt, wie und wann die Arbeit ausgeführt werden soll. Es gibt zwei konkrete Implementierungen der Klasse WorkRequest:
- Die Klasse
OneTimeWorkRequestist für einmalige Aufgaben vorgesehen. Eine einmalige Aufgabe wird nur einmal ausgeführt. - Die Klasse
PeriodicWorkRequestist für periodische Aufgaben vorgesehen, die sich in regelmäßigen Abständen wiederholen.
Aufgaben können einmalig oder regelmäßig sein. Wählen Sie die Klasse entsprechend aus. Weitere Informationen zum Planen wiederkehrender Aufgaben finden Sie in der Dokumentation zu wiederkehrenden Aufgaben.
In dieser Aufgabe definieren und planen Sie einen WorkRequest, um den Worker auszuführen, den Sie in der vorherigen Aufgabe erstellt haben.
Schritt 1: Wiederkehrende Aufgaben einrichten
In einer Android-App ist die Klasse Application die Basisklasse, die alle anderen Komponenten wie Aktivitäten und Dienste enthält. Wenn der Prozess für Ihre Anwendung oder Ihr Paket erstellt wird, wird die Application-Klasse (oder eine beliebige Unterklasse von Application) vor allen anderen Klassen instanziiert.
In dieser Beispiel-App ist die Klasse DevByteApplication eine Unterklasse der Klasse Application. Die Klasse DevByteApplication ist ein guter Ort, um die WorkManager zu planen.
- Erstellen Sie in der Klasse
DevByteApplicationeine Methode namenssetupRecurringWork(), um die wiederkehrende Hintergrundarbeit einzurichten.
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
}- Erstellen und initialisieren Sie in der Methode
setupRecurringWork()mit der MethodePeriodicWorkRequestBuilder()eine Anfrage für periodische Arbeitsvorgänge, die einmal täglich ausgeführt werden soll. Übergeben Sie die KlasseRefreshDataWorker, die Sie in der vorherigen Aufgabe erstellt haben. Geben Sie ein Wiederholungsintervall von1mit einer Zeiteinheit vonTimeUnit.DAYSan.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()Importieren Sie java.util.concurrent.TimeUnit, um den Fehler zu beheben.
Schritt 2: WorkRequest mit WorkManager planen
Nachdem Sie Ihre WorkRequest definiert haben, können Sie sie mit WorkManager über die Methode enqueueUniquePeriodicWork() planen. Mit dieser Methode können Sie der Warteschlange ein PeriodicWorkRequest mit einem eindeutigen Namen hinzufügen. Es kann jeweils nur ein PeriodicWorkRequest mit einem bestimmten Namen aktiv sein.
Möglicherweise soll beispielsweise nur ein Synchronisierungsvorgang aktiv sein. Wenn ein Synchronisierungsvorgang aussteht, können Sie ihn entweder ausführen lassen oder ihn mit Ihrer neuen Arbeit ersetzen. Verwenden Sie dazu eine ExistingPeriodicWorkPolicy.
Weitere Informationen zum Planen von WorkRequest finden Sie in der WorkManager-Dokumentation.
- Fügen Sie in der Klasse
RefreshDataWorkeram Anfang der Klasse ein Companion-Objekt hinzu. Definieren Sie einen Namen für den Worker, um ihn eindeutig zu identifizieren.
companion object {
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}- Planen Sie in der Klasse
DevByteApplicationam Ende der MethodesetupRecurringWork()die Arbeit mit der MethodeenqueueUniquePeriodicWork(). Übergeben Sie denKEEP-Enum für die ExistingPeriodicWorkPolicy. Übergeben SierepeatingRequestalsPeriodicWorkRequest-Parameter.
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)Wenn ausstehende (nicht abgeschlossene) Aufgaben mit demselben Namen vorhanden sind, sorgt der Parameter ExistingPeriodicWorkPolicy.KEEP dafür, dass die WorkManager die vorherige periodische Aufgabe beibehält und die neue Arbeitsanfrage verwirft.
- Erstellen Sie am Anfang der
DevByteApplication-Klasse einCoroutineScope-Objekt. Übergeben SieDispatchers.Defaultals Konstruktorparameter.
private val applicationScope = CoroutineScope(Dispatchers.Default)- Fügen Sie in der Klasse
DevByteApplicationeine neue Methode namensdelayedInit()hinzu, um eine Coroutine zu starten.
private fun delayedInit() {
applicationScope.launch {
}
}- Rufen Sie in der Methode
delayedInit()die MethodesetupRecurringWork()auf. - Verschieben Sie die Timber-Initialisierung von der Methode
onCreate()zur MethodedelayedInit().
private fun delayedInit() {
applicationScope.launch {
Timber.plant(Timber.DebugTree())
setupRecurringWork()
}
}- Fügen Sie in der Klasse
DevByteApplicationam Ende der MethodeonCreate()einen Aufruf der MethodedelayedInit()hinzu.
override fun onCreate() {
super.onCreate()
delayedInit()
}- Öffnen Sie unten im Android Studio-Fenster den Bereich Logcat. Nach
RefreshDataWorkerfiltern. - Führen Sie die App aus. Die
WorkManagerplant Ihre wiederkehrenden Aufgaben sofort.
Im Bereich Logcat sehen Sie die Log-Anweisungen, die zeigen, dass die Arbeitsanfrage geplant und dann erfolgreich ausgeführt wird.
D/RefreshDataWorker: Work request for sync is run I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
Das WM-WorkerWrapper-Log wird aus der WorkManager-Bibliothek angezeigt. Sie können diese Logmeldung also nicht ändern.
Schritt 3 (optional): WorkRequest für ein Mindestintervall planen
In diesem Schritt verringern Sie das Zeitintervall von 1 Tag auf 15 Minuten. So können Sie die Logs für eine Anfrage für periodische Arbeiten in Aktion sehen.
- Kommentieren Sie in der Klasse
DevByteApplicationin der MethodesetupRecurringWork()die aktuelle Definition vonrepeatingRequestaus. Fügen Sie eine neue Arbeitsanfrage mit einem periodischen Wiederholungsintervall von15Minuten hinzu.
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.build()- Öffnen Sie den Bereich Logcat in Android Studio und filtern Sie nach
RefreshDataWorker. Wenn Sie die vorherigen Logs löschen möchten, klicken Sie auf das Symbol Logcat leeren
. - Führen Sie die App aus. Die
WorkManagerplant Ihre wiederkehrenden Aufgaben sofort. Sehen Sie sich im Bereich Logcat die Logs an. Die Arbeitsanfrage wird alle 15 Minuten ausgeführt. Warten Sie 15 Minuten, um weitere Logs für Arbeitsanfragen zu sehen. Sie können die App geöffnet lassen oder schließen. Der Work Manager sollte trotzdem ausgeführt werden.
Das Intervall kann manchmal weniger als 15 Minuten und manchmal mehr als 15 Minuten betragen. (Der genaue Zeitpunkt hängt von den Akkuoptimierungen des Betriebssystems ab.)
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
Glückwunsch! Sie haben einen Worker erstellt und die Arbeitsanfrage mit WorkManager geplant. Es gibt jedoch ein Problem: Sie haben keine Einschränkungen angegeben. WorkManager plant die Arbeit einmal täglich ein, auch wenn der Akku des Geräts fast leer ist, das Gerät im Ruhemodus ist oder keine Netzwerkverbindung besteht. Dies wirkt sich auf den Akku und die Leistung des Geräts aus und kann zu einer schlechten Nutzererfahrung führen.
In der nächsten Aufgabe beheben Sie dieses Problem, indem Sie Einschränkungen hinzufügen.
In der vorherigen Aufgabe haben Sie WorkManager verwendet, um eine Arbeitsanfrage zu planen. In dieser Aufgabe fügen Sie Kriterien dafür hinzu, wann die Arbeit ausgeführt werden soll.
Beim Definieren von WorkRequest können Sie Einschränkungen für die Ausführung von Worker angeben. Sie können beispielsweise festlegen, dass die Arbeit nur ausgeführt werden soll, wenn das Gerät im Leerlauf ist oder nur, wenn das Gerät an eine Stromquelle angeschlossen und mit einem WLAN verbunden ist. Sie können auch eine Backoff-Richtlinie für das Wiederholen von Aufgaben angeben. Die unterstützten Einschränkungen sind die festgelegten Methoden in Constraints.Builder. Weitere Informationen finden Sie unter Arbeitsanfragen definieren.
Schritt 1: Constraints-Objekt hinzufügen und eine Einschränkung festlegen
In diesem Schritt erstellen Sie ein Constraints-Objekt und legen eine Einschränkung für das Objekt fest, nämlich eine Einschränkung für den Netzwerktyp. Es ist einfacher, die Logs mit nur einer Einschränkung zu sehen. In einem späteren Schritt fügen Sie weitere Einschränkungen hinzu.)
- Definieren Sie in der Klasse
DevByteApplicationam Anfang vonsetupRecurringWork()einevalvom TypConstraints. Verwenden Sie die MethodeConstraints.Builder().
val constraints = Constraints.Builder()Importieren Sie androidx.work.Constraints, um den Fehler zu beheben.
- Verwenden Sie die Methode
setRequiredNetworkType(), um demconstraints-Objekt eine Einschränkung für den Netzwerktyp hinzuzufügen. Verwenden Sie das EnumUNMETERED, damit die Arbeitsanfrage nur ausgeführt wird, wenn das Gerät mit einem Netzwerk verbunden ist, das nicht nach Volumen abgerechnet wird.
.setRequiredNetworkType(NetworkType.UNMETERED)- Verwenden Sie die Methode
build(), um die Einschränkungen aus dem Builder zu generieren.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()Jetzt müssen Sie das neu erstellte Constraints-Objekt für die Arbeitsanfrage festlegen.
- Legen Sie in der Klasse
DevByteApplicationin der MethodesetupRecurringWork()dasConstraints-Objekt auf die regelmäßige ArbeitsanfragerepeatingRequestfest. Fügen Sie die MethodesetConstraints()über dembuild()-Methodenaufruf ein, um die Einschränkungen festzulegen.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build()Schritt 2: App ausführen und Protokolle ansehen
In diesem Schritt führen Sie die App aus und sehen, dass die eingeschränkte Arbeitsanfrage in regelmäßigen Abständen im Hintergrund ausgeführt wird.
- Wenn Sie die App vom Gerät oder Emulator deinstallieren, werden alle zuvor geplanten Aufgaben abgebrochen.
- Öffnen Sie den Bereich Logcat in Android Studio. Löschen Sie im Bereich Logcat die vorherigen Logs, indem Sie links auf das Symbol Logcat löschen
klicken. Nach workfiltern. - Deaktivieren Sie das WLAN auf dem Gerät oder Emulator, damit Sie sehen können, wie Einschränkungen funktionieren. Im aktuellen Code wird nur eine Einschränkung festgelegt, die angibt, dass die Anfrage nur in einem Netzwerk mit unbegrenztem Datenvolumen ausgeführt werden soll. Da WLAN deaktiviert ist, ist das Gerät nicht mit dem Netzwerk verbunden, unabhängig davon, ob es sich um ein Netzwerk mit oder ohne Datenvolumenbegrenzung handelt. Daher wird diese Einschränkung nicht erfüllt.
- Führen Sie die App aus und sehen Sie sich den Bereich Logcat an. Mit
WorkManagerwird die Hintergrundaufgabe sofort geplant. Da die Netzwerkbeschränkung nicht erfüllt ist, wird die Aufgabe nicht ausgeführt.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
- Aktivieren Sie das WLAN auf dem Gerät oder Emulator und beobachten Sie den Bereich Logcat. Die geplante Hintergrundaufgabe wird jetzt ungefähr alle 15 Minuten ausgeführt, sofern die Netzwerkbeschränkung erfüllt ist.
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 [...]
Schritt 3: Weitere Einschränkungen hinzufügen
In diesem Schritt fügen Sie dem PeriodicWorkRequest die folgenden Einschränkungen hinzu:
- Der Akku ist nicht schwach.
- Gerät aufladen
- Gerät im Leerlauf: Nur ab API-Level 23 (Android M) verfügbar.
Implementieren Sie Folgendes in der Klasse DevByteApplication.
- Geben Sie in der Klasse
DevByteApplicationin der MethodesetupRecurringWork()an, dass die Arbeitsanfrage nur ausgeführt werden soll, wenn der Akku nicht schwach ist. Fügen Sie die Einschränkung vor dem Aufruf der Methodebuild()hinzu und verwenden Sie die MethodesetRequiresBatteryNotLow().
.setRequiresBatteryNotLow(true)- Aktualisieren Sie die Arbeitsanfrage so, dass sie nur ausgeführt wird, wenn das Gerät geladen wird. Fügen Sie die Einschränkung vor dem Aufruf der Methode
build()hinzu und verwenden Sie die MethodesetRequiresCharging().
.setRequiresCharging(true)- Aktualisieren Sie die Arbeitsanfrage so, dass sie nur ausgeführt wird, wenn das Gerät inaktiv ist. Fügen Sie die Einschränkung vor dem Methodenaufruf
build()hinzu und verwenden Sie die MethodesetRequiresDeviceIdle(). Bei dieser Einschränkung wird die Arbeitsanfrage nur ausgeführt, wenn der Nutzer das Gerät nicht aktiv verwendet. Diese Funktion ist nur unter Android 6.0 (Marshmallow) und höher verfügbar. Fügen Sie daher eine Bedingung für die SDK-VersionMund höher hinzu.
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}Hier finden Sie die vollständige Definition des constraints-Objekts.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()- Ändern Sie in der Methode
setupRecurringWork()das Anfrageintervall wieder auf einmal täglich.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()Hier ist die vollständige Implementierung der Methode setupRecurringWork() mit einem Log, damit Sie nachvollziehen können, wann die regelmäßige Arbeitsanfrage geplant ist.
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)
}- Wenn Sie die zuvor geplante Arbeitsanfrage entfernen möchten, deinstallieren Sie die DevBytes App von Ihrem Gerät oder Emulator.
- Führen Sie die App aus. Die Arbeitsanfrage wird sofort von
WorkManagergeplant. Die Arbeitsanfrage wird einmal täglich ausgeführt, wenn alle Einschränkungen erfüllt sind. - Diese Arbeitsanfrage wird im Hintergrund ausgeführt, solange die App installiert ist, auch wenn sie nicht ausgeführt wird. Aus diesem Grund sollten Sie die App vom Smartphone deinstallieren.
Gut gemacht! Sie haben eine akkusparende Arbeitsanfrage für das tägliche Vorabrufen von Videos in der DevBytes App implementiert und geplant. WorkManager plant und führt die Aufgabe aus und optimiert dabei die Systemressourcen. Ihre Nutzer und ihre Akkus werden sich freuen.
Android Studio-Projekt: DevBytesWorkManager.
- Mit der
WorkManagerAPI lassen sich aufschiebbare, asynchrone Aufgaben, die zuverlässig ausgeführt werden müssen, ganz einfach planen. - Die meisten Apps in der Praxis müssen lang andauernde Hintergrundaufgaben ausführen. Verwenden Sie
WorkManager, um einen Hintergrundtask auf optimierte und effiziente Weise zu planen. - Die wichtigsten Klassen in der
WorkManager-Bibliothek sindWorker,WorkRequestundWorkManager. - Die Klasse
Workerstellt eine Arbeitseinheit dar. Wenn Sie die Hintergrundaufgabe implementieren möchten, erweitern Sie die KlasseWorkerund überschreiben Sie die MethodedoWork(). - Die Klasse
WorkRequeststellt eine Anfrage zum Ausführen einer Arbeitseinheit dar.WorkRequestist die Basisklasse zum Angeben von Parametern für Aufgaben, die Sie inWorkManagerplanen. - Es gibt zwei konkrete Implementierungen der Klasse
WorkRequest:OneTimeWorkRequestfür einmalige Aufgaben undPeriodicWorkRequestfür periodische Arbeitsanfragen. - Wenn Sie die
WorkRequestdefinieren, können SieConstraintsangeben, um festzulegen, wann dieWorkerausgeführt werden soll. Zu den Einschränkungen gehört beispielsweise, ob das Gerät an eine Stromquelle angeschlossen ist, ob es sich im Leerlauf befindet oder ob eine WLAN-Verbindung besteht. - Wenn Sie dem
WorkRequestEinschränkungen hinzufügen möchten, verwenden Sie die in derConstraints.Builder-Dokumentation aufgeführten Set-Methoden. Wenn Sie beispielsweise angeben möchten, dassWorkRequestnicht ausgeführt werden soll, wenn der Akku des Geräts leer ist, verwenden Sie die MethodesetRequiresBatteryNotLow(). - Nachdem Sie die
WorkRequestdefiniert haben, übergeben Sie die Aufgabe an das Android-System. Planen Sie dazu die Aufgabe mit einer derWorkManager-enqueue-Methoden. - Der genaue Zeitpunkt der Ausführung von
Workerhängt von den Einschränkungen ab, die inWorkRequestverwendet werden, sowie von Systemoptimierungen.WorkManagerist so konzipiert, dass unter diesen Einschränkungen das bestmögliche Verhalten erzielt wird.
Udacity-Kurs:
Android-Entwicklerdokumentation:
- Arbeitsanfragen definieren
WorkManager- Erste Schritte mit WorkManager
- Wiederkehrende Aufgaben
- Leitfaden zur Hintergrundverarbeitung
Sonstiges:
In diesem Abschnitt werden mögliche Hausaufgaben für Schüler und Studenten aufgeführt, die dieses Codelab im Rahmen eines von einem Kursleiter geleiteten Kurses durcharbeiten. Es liegt in der Verantwortung des Kursleiters, Folgendes zu tun:
- Weisen Sie bei Bedarf Aufgaben zu.
- Teilen Sie den Schülern/Studenten mit, wie sie Hausaufgaben abgeben können.
- Benoten Sie die Hausaufgaben.
Lehrkräfte können diese Vorschläge nach Belieben nutzen und auch andere Hausaufgaben zuweisen, die sie für angemessen halten.
Wenn Sie dieses Codelab selbst durcharbeiten, können Sie mit diesen Hausaufgaben Ihr Wissen testen.
Frage 1
Was sind die konkreten Implementierungen der Klasse WorkRequest?
▢ OneTimeWorkPeriodicRequest
▢ OneTimeWorkRequest und PeriodicWorkRequest
▢ OneTimeWorkRequest und RecurringWorkRequest
▢ OneTimeOffWorkRequest und RecurringWorkRequest
Frage 2
Welche der folgenden Klassen verwendet WorkManager, um die Hintergrundaufgabe auf API 23 und höher zu planen?
▢ Nur JobScheduler
▢ BroadcastReceiver und AlarmManager
▢ AlarmManager und JobScheduler
▢ Scheduler und BroadcastReceiver
Frage 3
Welche API verwenden Sie, um einem WorkRequest Einschränkungen hinzuzufügen?
▢ setConstraints()
▢ addConstraints()
▢ setConstraint()
▢ addConstraintsToWorkRequest()
Links zu anderen Codelabs in diesem Kurs finden Sie auf der Landingpage für Android Kotlin Fundamentals-Codelabs.