Cómo definir tus WorkRequests

En la guía de introducción, se describió cómo crear un elemento WorkRequest simple y colocarlo en la cola.

En esta guía, aprenderás a personalizar las solicitudes de trabajo para controlar casos prácticos comunes, como los siguientes:

  • Cómo controlar las restricciones de tareas, como la disponibilidad de red
  • Cómo garantizar una demora mínima en la ejecución de la tarea
  • Cómo controlar los reintentos y retrocesos de tareas
  • Cómo controlar la entrada y salida de tareas
  • Cómo agrupar tareas con etiquetas

Restricciones de trabajos

Puedes agregar Constraints a tu trabajo con el fin de indicar cuándo se puede ejecutar.

Por ejemplo, puedes especificar que el trabajo solo se ejecute cuando el dispositivo esté inactivo y conectado a una fuente de alimentación.

En el siguiente código, se muestra cómo puedes agregar estas restricciones a OneTimeWorkRequest. Para obtener una lista completa de las restricciones admitidas, consulta la documentación de referencia de Constraints.Builder.

Kotlin


    // Create a Constraints object that defines when the task should run
    val constraints = Constraints.Builder()
            .setRequiresDeviceIdle(true)
            .setRequiresCharging(true)
            .build()

    // ...then create a OneTimeWorkRequest that uses those constraints
    val compressionWork = OneTimeWorkRequestBuilder<CompressWorker>()
            .setConstraints(constraints)
            .build()

    

Java

    // Create a Constraints object that defines when the task should run
    Constraints constraints = new Constraints.Builder()
        .setRequiresDeviceIdle(true)
        .setRequiresCharging(true)
         .build();

    // ...then create a OneTimeWorkRequest that uses those constraints
    OneTimeWorkRequest compressionWork =
                    new OneTimeWorkRequest.Builder(CompressWorker.class)
         .setConstraints(constraints)
         .build();
    

Cuando se especifican varias restricciones, tu tarea solo se ejecuta si se cumplen todas.

En caso de que falle una restricción mientras tu tarea se está ejecutando, WorkManager detendrá a su trabajador. Se intentará ejecutar la tarea nuevamente cuando se cumplan las restricciones.

Demoras iniciales

En el caso de que tu trabajo no tenga restricciones o que todas las restricciones se cumplan cuando tu trabajo esté en cola, el sistema podrá elegir ejecutar la tarea de inmediato. Si no quieres que la tarea se ejecute de inmediato, puedes especificar que el trabajo comience después de un retraso inicial mínimo.

A continuación, te mostramos un ejemplo de cómo configurar tu tarea para que se ejecute al menos 10 minutos después de que se haya puesto en cola.

Kotlin


    val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
            .setInitialDelay(10, TimeUnit.MINUTES)
            .build()

    

Java


    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInitialDelay(10, TimeUnit.MINUTES)
            .build();

    

Reintentos y política de retirada

Si necesitas que WorkManager vuelva a realizar tu tarea, puedes mostrar Result.retry() desde tu trabajador.

Entonces, tu trabajo se reprograma con una política y un retraso de retirada predeterminados. El retraso de retirada especifica la cantidad mínima de tiempo que se debe esperar antes de reintentar la ejecución del trabajo. La política de retirada define cómo aumentará el retraso de retirada con el tiempo para los siguientes reintentos. El valor predeterminado es EXPONENTIAL.

A continuación, puedes ver un ejemplo de cómo personalizar el retraso y la política de retirada.

Kotlin


    val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
            .setBackoffCriteria(
                    BackoffPolicy.LINEAR,
                    OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                    TimeUnit.MILLISECONDS)
            .build()

    

Java


    OneTimeWorkRequest uploadWorkRequest =
        new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setBackoffCriteria(
                    BackoffPolicy.LINEAR,
                    OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                    TimeUnit.MILLISECONDS)
            .build();
    

Cómo definir entradas y salidas para tu tarea

Es posible que tu tarea requiera que los datos se pasen como parámetros de entrada o que se muestren como resultado. Por ejemplo, una tarea que controla la subida de una imagen requiere que el URI de la imagen se suba como entrada y podría requerir que la URL de la imagen se suba como resultado.

Los valores de entrada y salida se almacenan como pares clave-valor en un objeto Data. En el siguiente código, se muestra cómo puedes establecer datos de entrada en tu WorkRequest.

Kotlin


    // workDataOf (part of KTX) converts a list of pairs to a [Data] object.
    val imageData = workDataOf(Constants.KEY_IMAGE_URI to imageUriString)

    val uploadWorkRequest = OneTimeWorkRequestBuilder<UploadWorker>()
            .setInputData(imageData)
            .build()

    

Java


    Data imageData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URI, imageUriString)
                    .build();

    OneTimeWorkRequest uploadWorkRequest = new OneTimeWorkRequest.Builder(UploadWorker.class)
            .setInputData(imageData)
            .build()
    

La clase Worker puede acceder a los argumentos de entrada llamando a Worker.getInputData().

Del mismo modo, se puede utilizar la clase Data para generar un valor de retorno. Si quieres mostrar el objeto Data, inclúyelo en el elemento Result, en Result.success() o Result.failure(), como se muestra a continuación.

Kotlin

    class UploadWorker(appContext: Context, workerParams: WorkerParameters)
        : Worker(appContext, workerParams) {

        override fun doWork(): Result {

                // Get the input
                val imageUriInput = getInputData().getString(Constants.KEY_IMAGE_URI)
                // TODO: validate inputs.
                // Do the work
                val response = uploadFile(imageUriInput)

                // Create the output of the work
                val outputData = workDataOf(Constants.KEY_IMAGE_URL to response.imageUrl)

                // Return the output
                return Result.success(outputData)

        }
    }

    

Java

    public class UploadWorker extends Worker {

        public UploadWorker(
            @NonNull Context context,
            @NonNull WorkerParameters params) {
            super(context, params);
        }

        @Override
        public Result doWork() {

            // Get the input
            String imageUriInput = getInputData().getString(Constants.KEY_IMAGE_URI)
            // TODO: validate inputs.
            // Do the work
            Response response = uploadFile(imageUriInput)

            // Create the output of the work
            Data outputData = new Data.Builder
                    .putString(Constants.KEY_IMAGE_URL, response.imageUrl)
                    .build();

            // Return the output
            return Result.success(outputData)
        }
    }
    

Trabajo de etiquetado

Puedes agrupar tus tareas de manera lógica mediante la asignación de una string de etiqueta a cualquier objeto WorkRequest. Esto te permite operar en todas las tareas con una etiqueta en particular.

Por ejemplo, WorkManager.cancelAllWorkByTag(String) cancela todas las tareas con una etiqueta en particular y WorkManager.getWorkInfosByTagLiveData(String) muestra un elemento LiveData con una lista del estado de todas las tareas con esa etiqueta.

En el siguiente código, se muestra cómo puedes agregar una etiqueta de "limpieza" a tu tarea con WorkRequest.Builder.addTag(String):

Kotlin

    val cacheCleanupTask =
            OneTimeWorkRequestBuilder<CacheCleanupWorker>()
        .setConstraints(constraints)
        .addTag("cleanup")
        .build()
    

Java

    OneTimeWorkRequest cacheCleanupTask =
            new OneTimeWorkRequest.Builder(CacheCleanupWorker.class)
        .setConstraints(constraints)
        .addTag("cleanup")
        .build();