Para los usuarios de Kotlin, WorkManager proporciona compatibilidad de primera clase con corrutinas. Para comenzar, incluye work-runtime-ktx
en tu archivo de Gradle. En lugar de extender Worker
, deberías extender CoroutineWorker
, que tiene una versión con suspensión de doWork()
. Por ejemplo, si quieres compilar un CoroutineWorker
simple para realizar algunas operaciones de red, debes hacer lo siguiente:
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()
}
}
Ten en cuenta que CoroutineWorker.doWork()
es una función de suspensión. A diferencia de Worker
, este código no se ejecuta en el Executor
especificado en tu Configuration
. En cambio, la opción predeterminada es Dispatchers.Default
. Puedes personalizarlo si proporcionas tu propio CoroutineContext
. En el ejemplo anterior, es probable que desees realizar el siguiente trabajo en Dispatchers.IO
:
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
controla las detenciones automáticamente mediante la cancelación de la corrutina y la propagación de los indicadores de cancelación. No es necesario que hagas nada especial para controlar las interrupciones de trabajo.
Cómo ejecutar un CoroutineWorker en un proceso diferente
También puedes vincular un trabajador a un proceso específico mediante RemoteCoroutineWorker
, que es una implementación de ListenableWorker
.
RemoteCoroutineWorker
vincula un proceso específico con dos argumentos adicionales que puedes proporcionar como parte de los datos de entrada cuando compilas la solicitud de trabajo: ARGUMENT_CLASS_NAME
y ARGUMENT_PACKAGE_NAME
.
En el siguiente ejemplo, se muestra cómo compilar una solicitud de trabajo vinculada a un proceso 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
, también debes agregar una definición del servicio en el archivo 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>