Threading in CoroutineWorker

Per gli utenti di Kotlin, WorkManager offre un'assistenza di prim'ordine per le coroutine. Per ottenere hai iniziato, includi work-runtime-ktx nel file Gradle. Invece di estendere Worker, devi estendere CoroutineWorker, che ha una sospensione di doWork(). Ad esempio, se vuoi creare una semplice CoroutineWorker per eseguire alcune operazioni di rete, procedi nel seguente modo:

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()
    }
}

Tieni presente che CoroutineWorker.doWork() è una sospensione personalizzata. A differenza di Worker, questo codice non viene eseguito sul Executor specificato nel tuo Configuration. Invece, il valore predefinito è Dispatchers.Default. Puoi personalizzare questa opzione fornendo il tuo CoroutineContext. Nell'esempio precedente, probabilmente vorrai eseguire questa operazione su Dispatchers.IO, nel seguente modo:

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 gestisce le interruzioni automaticamente annullando la coroutine e propagare i segnali di annullamento. Non devi fare nulla di speciale per gestire le interruzioni del lavoro.

Esecuzione di un CoroutineWorker in un processo diverso

Puoi anche associare un worker a un processo specifico utilizzando RemoteCoroutineWorker, un'implementazione di ListenableWorker.

RemoteCoroutineWorker si associa a un processo specifico con due argomenti aggiuntivi che fornisci come parte dei dati di input durante la creazione della richiesta di lavoro: ARGUMENT_CLASS_NAME e ARGUMENT_PACKAGE_NAME.

L'esempio seguente mostra la creazione di una richiesta di lavoro associata a un una procedura specifica:

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();

Per ogni RemoteWorkerService, devi aggiungere anche una definizione di servizio in il tuo file AndroidManifest.xml:

<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>

Campioni