Como observar o andamento intermediário do worker

O WorkManager 2.3.0-alpha01 oferece compatibilidade de primeira classe para definir e observar o andamento intermediário de workers. Se o worker estava em execução enquanto o app estava em primeiro plano, essas informações também podem ser exibidas para o usuário usando APIs que retornam o LiveData de WorkInfo.

O ListenableWorker agora oferece compatibilidade com a API setProgressAsync(), que possibilita que ele se mantenha no andamento intermediário. Essas APIs permitem que os desenvolvedores definam um andamento intermediário que pode ser observado pela IU. O andamento é representado pelo tipo Data, que é um contêiner serializável de propriedades, semelhante a input e output e sujeito às mesmas restrições.

As informações de andamento só podem ser observadas e atualizadas enquanto o ListenableWorker está em execução. As tentativas de definir o andamento em um ListenableWorker após o término da execução serão ignoradas. Também é possível observar informações de progresso usando um dos métodos getWorkInfoBy…() ou getWorkInfoBy…LiveData(). Esses métodos retornam instâncias de WorkInfo, que tem um novo método getProgress() que retorna Data.

Como atualizar o andamento

Para desenvolvedores Java que usam ListenableWorker ou Worker, a API setProgressAsync() retorna um ListenableFuture<Void>. A atualização do andamento é assíncrona, já que o processo de atualização envolve o armazenamento de informações em um banco de dados. Em Kotlin, você pode usar a função de extensão setProgress() do objeto CoroutineWorker para atualizar informações de andamento.

Este exemplo mostra um ProgressWorker simples. O Worker configura o andamento como 0 quando é iniciado e, após a conclusão, atualiza o valor do andamento para 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();
    }
}

Observar o andamento

Observar as informações de andamento também é simples. Você pode usar os métodos getWorkInfoBy…() ou getWorkInfoBy…LiveData() para ver uma referência a WorkInfo.

Veja um exemplo que usa a 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 ver mais documentação sobre como observar objetos Worker, leia Estados de trabalho e como observar trabalhos.