Für Kotlin-Nutzer bietet WorkManager erstklassigen Support für Koroutinen. Füge zuerst work-runtime-ktx
in deine Gradle-Datei ein. Anstatt Worker
zu erweitern, sollten Sie CoroutineWorker
erweitern, das die haltende Version doWork()
hat. Wenn Sie beispielsweise ein einfaches CoroutineWorker
-Element für einige Netzwerkvorgänge erstellen möchten, gehen Sie so vor:
class CoroutineDownloadWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
val data = downloadSynchronously("https://www.google.com")
saveData(data)
return Result.success()
}
}
CoroutineWorker.doWork()
ist eine ausgesetzte Funktion. Im Gegensatz zu Worker
wird dieser Code nicht auf dem Executor
ausgeführt, der in der Configuration
angegeben ist. Stattdessen wird standardmäßig Dispatchers.Default
verwendet. Sie können dies anpassen, indem Sie Ihre eigene CoroutineContext
angeben. Im obigen Beispiel würden Sie dies am besten für Dispatchers.IO
tun:
class CoroutineDownloadWorker(
context: Context,
params: WorkerParameters
) : CoroutineWorker(context, params) {
override suspend fun doWork(): Result {
withContext(Dispatchers.IO) {
val data = downloadSynchronously("https://www.google.com")
saveData(data)
return Result.success()
}
}
}
CoroutineWorker
verarbeitet Haltestellen automatisch, indem die Koroutine abgebrochen und die Abbruchsignale weitergegeben werden. Für den Umgang mit Unterbrechungen von Aufgaben sind keine besonderen Maßnahmen erforderlich.
CoroutineWorker in einem anderen Prozess ausführen
Sie können einen Worker auch mit RemoteCoroutineWorker
, einer Implementierung von ListenableWorker
, an einen bestimmten Prozess binden.
RemoteCoroutineWorker
bindet sich mit zwei zusätzlichen Argumenten an einen bestimmten Prozess, die Sie beim Erstellen der Arbeitsanfrage als Teil der Eingabedaten angeben: ARGUMENT_CLASS_NAME
und ARGUMENT_PACKAGE_NAME
.
Das folgende Beispiel zeigt, wie eine Arbeitsanfrage erstellt wird, die an einen bestimmten Prozess gebunden ist:
Kotlin
val PACKAGE_NAME = "com.example.background.multiprocess" val serviceName = RemoteWorkerService::class.java.name val componentName = ComponentName(PACKAGE_NAME, serviceName) val data: Data = Data.Builder() .putString(ARGUMENT_PACKAGE_NAME, componentName.packageName) .putString(ARGUMENT_CLASS_NAME, componentName.className) .build() return OneTimeWorkRequest.Builder(ExampleRemoteCoroutineWorker::class.java) .setInputData(data) .build()
Java
String PACKAGE_NAME = "com.example.background.multiprocess"; String serviceName = RemoteWorkerService.class.getName(); ComponentName componentName = new ComponentName(PACKAGE_NAME, serviceName); Data data = new Data.Builder() .putString(ARGUMENT_PACKAGE_NAME, componentName.getPackageName()) .putString(ARGUMENT_CLASS_NAME, componentName.getClassName()) .build(); return new OneTimeWorkRequest.Builder(ExampleRemoteCoroutineWorker.class) .setInputData(data) .build();
Für jede RemoteWorkerService
müssen Sie außerdem eine Dienstdefinition in die AndroidManifest.xml
-Datei einfügen:
<manifest ... > <service android:name="androidx.work.multiprocess.RemoteWorkerService" android:exported="false" android:process=":worker1" /> <service android:name=".RemoteWorkerService2" android:exported="false" android:process=":worker2" /> ... </manifest>