WorkManager te permite crear y poner en cola una cadena de trabajo que especifica varias tareas dependientes. Además, define el orden en el que deberían ejecutarse. Esta funcionalidad resulta particularmente útil cuando necesitas ejecutar varias tareas en un orden específico.
A fin de crear una cadena de trabajo, puedes usar WorkManager.beginWith(OneTimeWorkRequest)
o WorkManager.beginWith(List<OneTimeWorkRequest>)
, que mostrarán una instancia de WorkContinuation
cada uno.
Luego, puedes usar un objeto WorkContinuation
para agregar instancias dependientes de OneTimeWorkRequest
mediante then(OneTimeWorkRequest)
o then(List<OneTimeWorkRequest>)
.
Cada invocación de WorkContinuation.then(...)
muestra una nueva instancia de WorkContinuation
. Si agregas un elemento List
de las instancias de OneTimeWorkRequest
, estas solicitudes pueden ejecutarse en paralelo.
Por último, puedes usar el método WorkContinuation.enqueue()
para poner en cola (enqueue()
) tu cadena de WorkContinuation
.
Veamos un ejemplo. En él se configuran 3 trabajos con distintos trabajadores para ejecutarse (posiblemente en paralelo). Luego, se unen los resultados de estos trabajadores y se pasan a un trabajo que se almacena en caché. Por último, el resultado de ese trabajo se pasa a un trabajador de carga, que sube los resultados a un servidor remoto.
Kotlin
WorkManager.getInstance(myContext) // Candidates to run in parallel .beginWith(listOf(plantName1, plantName2, plantName3)) // Dependent work (only runs after all previous work in chain) .then(cache) .then(upload) // Call enqueue to kick things off .enqueue()
Java
WorkManager.getInstance(myContext) // Candidates to run in parallel .beginWith(Arrays.asList(plantName1, plantName2, plantName3)) // Dependent work (only runs after all previous work in chain) .then(cache) .then(upload) // Call enqueue to kick things off .enqueue();
Combinadores de entradas
Cuando encadenas instancias de OneTimeWorkRequest
, el resultado de las solicitudes de trabajo superiores se pasa como entrada a las secundarias. En el ejemplo anterior, las salidas de plantName1
, plantName2
y plantName3
se pasarían como entradas a la solicitud de cache
.
Para administrar las entradas de varias solicitudes de trabajos superiores, WorkManager usa InputMerger
.
WorkManager proporciona dos tipos diferentes de InputMerger
:
OverwritingInputMerger
trata de agregar todas las claves de todas las entradas en el resultado. En caso de conflictos, reemplaza las claves definidas anteriormente.ArrayCreatingInputMerger
trata de combinar las entradas y crea arreglos cada vez que sea necesario.
Si tienes algún caso de uso más específico, puedes escribir tu propio combinador y subclasificar InputMerger
.
OverwriteInputMerger
OverwritingInputMerger
es el método de combinación predeterminado. Si hay conflictos de claves en la combinación, el valor más reciente de una clave reemplazará cualquier versión anterior en los datos de salida que se generen.
Por ejemplo, si las entradas de plantas tienen una clave que coincide con sus respectivos nombres de variables ("plantName1"
, "plantName2"
y "plantName3"
), los datos que se pasan al trabajador cache
tendrán tres pares clave-valor.
Si hay un conflicto, el último trabajador en finalizar será el "ganador", por lo que su valor se pasará a cache
.
Dado que las solicitudes de trabajo se ejecutan en paralelo, no se puede garantizar el orden exacto en el que se ejecutarán. En el ejemplo anterior, plantName1
podría contener el valor de "tulip"
o "elm"
según el último que se escriba. En el caso de que exista la posibilidad de generarse un conflicto de claves y necesites conservar todos los datos de salida en una combinación, ArrayCreatingInputMerger
podría resultar más adecuado.
ArrayCreatingInputMerger
Para el ejemplo anterior, dado que deseamos preservar los resultados de todos los trabajadores de nombres de plantas, deberíamos usar un objeto ArrayCreatingInputMerger
.
Kotlin
val cache: OneTimeWorkRequest = OneTimeWorkRequestBuilder<PlantWorker>() .setInputMerger(ArrayCreatingInputMerger::class) .setConstraints(constraints) .build()
Java
OneTimeWorkRequest cache = new OneTimeWorkRequest.Builder(PlantWorker.class) .setInputMerger(ArrayCreatingInputMerger.class) .setConstraints(constraints) .build();
ArrayCreatingInputMerger
vincula cada clave con un arreglo. Si cada clave es única, se obtendrá como resultado una serie de arreglos de un solo elemento.
Si hay una colisión de claves, los valores correspondientes se agrupan en un arreglo.
Estados de trabajo y encadenado
Las cadenas de OneTimeWorkRequest
se ejecutan de forma secuencial si el trabajo se completa correctamente (es decir, muestran Result.success()
). Mientras se ejecutan las solicitudes de trabajo, estas podrían cancelarse o se podrían producir errores, lo que afectaría las solicitudes dependientes que siguen.
Cuando el primer elemento OneTimeWorkRequest
se pone en cola en una cadena de solicitudes de trabajo, se bloquean todas las solicitudes posteriores hasta que se completa la primera.
Una vez que esté en cola y se cumplan todas las restricciones de trabajo, se comenzará a ejecutar la primera solicitud. Si el trabajo se completa correctamente en el elemento raíz OneTimeWorkRequest
o List<OneTimeWorkRequest>
(es decir que muestra Result.success()
), se pondrá en cola el siguiente conjunto de solicitudes de trabajo dependientes.
Mientras cada solicitud de trabajo se complete correctamente, este mismo patrón se propagará al resto de la cadena hasta que se completen todos los trabajos. Si bien esta es la manera más sencilla y de mayor preferencia, también es importante controlar los estados de error.
Cuando se produce un error mientras un trabajador está procesando tu solicitud, puedes volver a intentarlo según la política de retirada que definas. Si reintentas una solicitud que forma parte de una cadena, solo se volverá a intentar ejecutar esa solicitud con los datos de entrada proporcionados. No se verá afectado ningún trabajo que se ejecute en paralelo.
A fin de obtener más información para definir estrategias de reintento personalizadas, consulta Política de retirada y reintento.
Si esa política de reintento no está definida o se agotó, o bien si alcanzas algún estado en el que un elemento OneTimeWorkRequest
muestra Result.failure()
, esa solicitud de trabajo y las demás solicitudes dependientes se marcarán como FAILED.
Se aplica la misma lógica cuando se cancela un elemento OneTimeWorkRequest
. Las solicitudes de trabajo dependientes también se marcan como CANCELLED
, por lo que no se ejecutarán sus trabajos.
Ten en cuenta que, si agregas más solicitudes de trabajo a una cadena con solicitudes fallidas o canceladas, las nuevas solicitudes también se marcarán como FAILED
o CANCELLED
, respectivamente. Si quieres extender el trabajo de una cadena existente, consulta APPEND_OR_REPLACE
en ExistingWorkPolicy.
Cuando creas cadenas de solicitudes de trabajo, debes definir políticas de reintento en las solicitudes dependientes para asegurarte de que el trabajo se complete siempre de manera oportuna. Las solicitudes de trabajo fallidas podrían generar cadenas incompletas o estados inesperados.
Para obtener más información, consulta Cómo cancelar y detener el trabajo.