Como criar threads no CoroutineWorker

Para usuários do Kotlin, o WorkManager oferece compatibilidade de primeira classe com corrotinas. Para começar, inclua work-runtime-ktx no arquivo do Gradle. Em vez de estender Worker, estenda CoroutineWorker, que tem uma versão de suspensão de doWork(). Por exemplo, se você quiser criar um CoroutineWorker simples para executar algumas operações de rede, faça o seguinte:

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

Observe que CoroutineWorker.doWork() é uma função de suspensão. Ao contrário de Worker, esse código não é executado no Executor especificado na Configuration. Em vez disso, o padrão é Dispatchers.Default. Você pode personalizar isso fornecendo seu próprio CoroutineContext. No exemplo acima, você provavelmente faria esse trabalho em Dispatchers.IO, da seguinte forma:

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 processa as interrupções automaticamente, cancelando a corrotina e propagando os sinais de cancelamento. Você não precisa fazer nada especial para processar as interrupções de trabalho.

Como executar um CoroutineWorker em um processo diferente

Também é possível vincular um worker a um processo específico usando RemoteCoroutineWorker, uma implementação de ListenableWorker.

RemoteCoroutineWorker se vincula a um processo específico com dois argumentos extras que você fornece como parte dos dados de entrada ao criar a solicitação de trabalho: ARGUMENT_CLASS_NAME e ARGUMENT_PACKAGE_NAME.

O exemplo a seguir demonstra a criação de uma solicitação de trabalho vinculada a um processo específico:

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

Para cada RemoteWorkerService, também é preciso adicionar uma definição de serviço no arquivo 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>

Exemplos