Cómo observar el progreso intermedio de trabajadores

WorkManager tiene asistencia de primera clase para establecer 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 con las APIs que muestran el LiveData de WorkInfo.

ListenableWorker ahora admite la API de 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 con el tipo Data, que es un contenedor serializable de propiedades (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 uno de los métodos getWorkInfoBy…() o getWorkInfoBy…LiveData(). Estos métodos muestran instancias de WorkInfo, que tiene un método getProgress() nuevo 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 de progreso en una base de datos. En Kotlin, puedes usar la función de extensión setProgress() del objeto CoroutineWorker para actualizar la información de progreso.

En este ejemplo, se muestra un ProgressWorker simple. El 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.