Cómo observar el progreso intermedio de un trabajador

WorkManager 2.3.0-alpha01 agrega compatibilidad de primera clase para configurar y observar el progreso intermedio de los trabajadores. Si el trabajador se estaba ejecutando mientras la app estaba en primer plano, esta información también se puede mostrar al usuario mediante las API que muestran LiveData de WorkInfo.

ListenableWorker ahora es compatible con la API setProgressAsync(), que le permite conservar el progreso intermedio. Estas API permiten a los desarrolladores establecer un progreso intermedio que la IU puede observar. El progreso se representa mediante el tipo de Data, que es un contenedor de propiedades serializable (similar a input y output, y sujeto a las mismas restricciones).

La información de progreso solo se puede observar y actualizar mientras se ejecuta ListenableWorker. Se ignoran los intentos de establecer el progreso en un ListenableWorker después de completar su ejecución. También puedes observar la información del progreso mediante los métodos getWorkInfoBy…() o getWorkInfoBy…LiveData(). Estos métodos muestran instancias de WorkInfo, que tiene un nuevo método getProgress() que muestra Data.

Actualización del progreso

Para los desarrolladores de Java que usan un ListenableWorker o un Worker, la API setProgressAsync() muestra un ListenableFuture<Void>; la actualización del progreso es asíncrona, dado que el proceso de actualización implica almacenar información del progreso en una base de datos. En Kotlin, se puede utilizar la función de extensión setProgress() del objeto CoroutineWorker para actualizar la información del progreso.

En este ejemplo, se muestra un ProgressWorker simple. El elemento Worker establece su progreso en 0 cuando comienza y, cuando se completa, actualiza el valor de progreso a 100.

Kotlin

    import android.content.Context
    import androidx.work.CoroutineWorker
    import androidx.work.Data
    import androidx.work.WorkerParameters
    import kotlinx.coroutines.delay

    class ProgressWorker(context: Context, parameters: WorkerParameters) :
        CoroutineWorker(context, parameters) {

        companion object {
            const val Progress = "Progress"
            private const val delayDuration = 1L
        }

        override suspend fun doWork(): Result {
            val firstUpdate = workDataOf(Progress to 0)
            val lastUpdate = workDataOf(Progress to 100)
            setProgress(firstUpdate)
            delay(delayDuration)
            setProgress(lastUpdate)
            return Result.success()
        }
    }
    

Java

    import android.content.Context;
    import androidx.annotation.NonNull;
    import androidx.work.Data;
    import androidx.work.Worker;
    import androidx.work.WorkerParameters;

    public class ProgressWorker extends Worker {

        private static final String PROGRESS = "PROGRESS";
        private static final long DELAY = 1000L;

        public ProgressWorker(
            @NonNull Context context,
            @NonNull WorkerParameters parameters) {
            super(context, parameters);
            // Set initial progress to 0
            setProgressAsync(new Data.Builder().putInt(PROGRESS, 0).build());
        }

        @NonNull
        @Override
        public Result doWork() {
            try {
                // Doing work.
                Thread.sleep(DELAY);
            } catch (InterruptedException exception) {
                // ... handle exception
            }
            // Set progress to 100 after you are done doing your work.
            setProgressAsync(new Data.Builder().putInt(PROGRESS, 100).build());
            return Result.success();
        }
    }
    

Observación del progreso

Observar la información del progreso también es simple. Puedes usar los métodos getWorkInfoBy…() o getWorkInfoBy…LiveData() y obtener una referencia a WorkInfo.

A continuación, verás un ejemplo que usa la API getWorkInfoByIdLiveData.

Kotlin

    WorkManager.getInstance(applicationContext)
        // requestId is the WorkRequest id
        .getWorkInfoByIdLiveData(requestId)
        .observe(observer, Observer { workInfo: WorkInfo? ->
                if (workInfo != null) {
                    val progress = workInfo.progress
                    val value = progress.getInt(Progress, 0)
                    // Do something with progress information
                }
        })
    

Java

    WorkManager.getInstance(getApplicationContext())
         // requestId is the WorkRequest id
         .getWorkInfoByIdLiveData(requestId)
         .observe(lifecycleOwner, new Observer<WorkInfo>() {
                 @Override
                 public void onChanged(@Nullable WorkInfo workInfo) {
                     if (workInfo != null) {
                         Data progress = workInfo.getProgress();
                         int value = progress.getInt(PROGRESS, 0)
                         // Do something with progress
                 }
          }
    });
    

Para obtener más documentación sobre la observación de objetos Worker, lee Estados y observación de los trabajos.