Actualiza el trabajo que ya está en cola

WorkManager te permite actualizar un WorkRequest después de se lo pusieron en cola. Esto suele ser necesario en las apps más grandes que cambian con frecuencia restricciones o que necesiten actualizar a sus trabajadores sobre la marcha. A partir de WorkManager versión 2.8.0, puedes hacerlo con la API de updateWork().

El método updateWork() te permite cambiar ciertos aspectos de un WorkRequest sobre la marcha, sin tener que realizar el proceso de cancelar y colocar en cola una nueva. Esto simplifica notablemente el proceso el proceso de administración de recursos.

Evita cancelar trabajos

Por lo general, debes evitar cancelar una WorkRequest existente y colocar una nueva uno. Si lo haces, es posible que la app repita ciertas tareas para escribir una cantidad significativa de código adicional.

Considera los siguientes ejemplos en los que cancelar una WorkRequest puede causar dificultades:

  • Solicitud de backend: Si cancelas una Worker mientras se procesa una carga útil para enviar al servidor, el nuevo Worker debe volver a empezar y volver a procesar la carga útil potencialmente costosa.
  • Programación: Si cancelas un PeriodicWorkRequest y quieres como la nueva PeriodicWorkRequest para ejecutarse de acuerdo con la misma programación, necesitas para calcular una compensación horaria para garantizar que el nuevo tiempo de ejecución esté alineado con la solicitud de trabajo anterior.

La API de updateWork() te permite actualizar las restricciones de una solicitud de trabajo y otros parámetros sin la molestia de cancelar y poner en cola una nueva solicitud.

Cuándo cancelar el trabajo

Hay casos en los que debes cancelar directamente un WorkRequest en lugar de llama a updateWork(). Esto es lo que debes hacer cuando quieras cambiar el la naturaleza fundamental del trabajo que has puesto en cola.

Cuándo actualizar el trabajo

Imagina una app de fotos que hace una copia de seguridad diaria de las fotos del usuario. Tiene puso en cola un PeriodicWorkRequest para hacerlo. La WorkRequest tiene restricciones que requieran que el dispositivo se esté cargando y esté conectado a Wi-Fi.

Sin embargo, el usuario solo carga el dispositivo por 20 minutos diarios con un cargador. En este caso, es posible que la app quiera actualizar WorkRequest para relajar la restricción de carga, para que pueda subir las fotos, incluso si el dispositivo no está completamente cargada.

En este caso, puedes usar el método updateWork() para actualizar el trabajo las restricciones de la solicitud.

Cómo actualizar el trabajo

El método updateWork() brinda un medio sencillo para actualizar un WorkRequest, sin tener que cancelar y poner en cola uno nuevo.

Para usar la actualización del trabajo en cola, sigue estos pasos:

  1. Obtener el ID existente para el trabajo en cola: Obtén el ID de la WorkRequest que quieres actualizar. Puedes recuperar este ID con cualquiera de getWorkInfo, o si conservas manualmente el ID de la inicial WorkRequest para recuperación posterior con la propiedad pública WorkRequest.id, antes de colocarlo en la cola.
  2. Crear una WorkRequest nueva: Crea un WorkRequest nuevo y usa WorkRequest.Builder.setID() para establecer su ID de modo que coincida con el del dominio WorkRequest
  3. Establece restricciones: Usa WorkRequest.Builder.setConstraints() para pasar el Restricciones nuevas de WorkManager.
  4. Llamar a updateWork: Pasa la nueva WorkRequest a updateWork().

Ejemplo de actualización de trabajo

Este es un ejemplo de fragmento de código en Kotlin que demuestra cómo usar el Método updateWork() para cambiar las restricciones de batería de un WorkRequest usado Para subir fotos, sigue estos pasos:

suspend fun updatePhotoUploadWork() {
    // Get instance of WorkManager.
    val workManager = WorkManager.getInstance(context)

    // Retrieve the work request ID. In this example, the work being updated is unique
    // work so we can retrieve the ID using the unique work name.
    val photoUploadWorkInfoList = workManager.getWorkInfosForUniqueWork(
        PHOTO_UPLOAD_WORK_NAME
    ).await()

    val existingWorkRequestId = photoUploadWorkInfoList.firstOrNull()?.id ?: return

    // Update the constraints of the WorkRequest to not require a charging device.
    val newConstraints = Constraints.Builder()
        // Add other constraints as required here.
        .setRequiresCharging(false)
        .build()

    // Create new WorkRequest from existing Worker, new constraints, and the id of the old WorkRequest.
    val updatedWorkRequest: WorkRequest =
        OneTimeWorkRequestBuilder<MyWorker>()
            .setConstraints(newConstraints)
            .setId(existingWorkRequestId)
            .build()

    // Pass the new WorkRequest to updateWork().
    workManager.updateWork(updatedWorkRequest)
}

Cómo controlar el resultado

updateWork() muestra un ListenableFuture<UpdateResult>. El dado UpdateResult puede tener uno de los diversos valores que describen si es o no WorkManager pudo aplicar tus cambios. También indica cuándo se pudo para aplicar el cambio.

Para obtener más información, consulta los updateWork() y UpdateResult. referencia.

Realiza un seguimiento del trabajo por generaciones

Cada vez que actualizas un WorkRequest, su generación se incrementa en uno. Esta te permite hacer un seguimiento exacto del WorkRequest que está actualmente en cola. Las generaciones te brindan más control cuando observas, rastreas y pruebas el trabajo solicitudes.

Para obtener la generación de un WorkRequest, sigue estos pasos:

  1. WorkInfo: Llama a WorkManager.getWorkInfoById() para recuperar una instancia. de WorkInfo correspondientes a tu WorkRequest.
  2. getGeneration: Llama a getGeneration() en la instancia de WorkInfo El Int que se muestra corresponde a la generación del WorkRequest
    • Ten en cuenta que no hay un campo o una propiedad de generación, solo WorkInfo.getGeneration().

Ejemplo de generación de pistas

El siguiente es un ejemplo de implementación del flujo de trabajo descrito anteriormente para y recupera la generación de un WorkRequest.

// Get instance of WorkManager.
val workManager = WorkManager.getInstance(context)

// Retrieve WorkInfo instance.
val workInfo = workManager.getWorkInfoById(oldWorkRequestId)

// Call getGeneration to retrieve the generation.
val generation = workInfo.getGeneration()

Políticas para actualizar el trabajo

Anteriormente, la solución recomendada para actualizar el trabajo periódico era poner en cola PeriodicWorkRequest por la política ExistingPeriodicWorkPolicy.REPLACE Si había un PeriodicWorkRequest pendiente con el mismo id único, el nuevo la solicitud de trabajo la cancelaría y la borraría. Esta política ahora está obsoleta en favorecer el flujo de trabajo con ExistingPeriodicWorkPolicy.UPDATE.

Por ejemplo, cuando usas enqueueUniquePeriodicWork con una PeriodicWorkRequest, puedes inicializar el nuevo PeriodicWorkRequest con el ExistingPeriodicWorkPolicy.UPDATE. Si hay una solicitud PeriodicWorkRequest con el mismo nombre único, WorkManager lo actualiza al nueva especificación. Con este flujo de trabajo, no es necesario usar updateWork()