Threads in CoroutineWorker

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>

Produktproben