Threading in CoroutineWorker

Per gli utenti di Kotlin, WorkManager offre un'assistenza di primo livello per le coroutine. Per iniziare, includi work-runtime-ktx nel file gradle. Anziché estendere Worker, ti consigliamo di estendere CoroutineWorker, che ha una versione sospesa di doWork(). Ad esempio, se vuoi creare un CoroutineWorker semplice per eseguire alcune operazioni di rete, procedi come segue:

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 funzione di sospensione. A differenza di Worker, questo codice non viene eseguito sul Executor specificato in Configuration. Il valore predefinito è Dispatchers.Default. Puoi personalizzare questa impostazione 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 automaticamente le interruzioni annullando la coroutine e propagando i segnali di cancellazione. Non devi fare nulla di particolare per gestire gli interruzioni del lavoro.

Esecuzione di 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 da te forniti 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 processo specifico:

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 anche aggiungere una definizione di servizio nel 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>

Samples