Observar o andamento intermediário do worker

O WorkManager tem suporte integrado 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 mostradas para o usuário usando APIs que retornam o LiveData de WorkInfo.

O ListenableWorker agora oferece suporte à 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.

Atualizar progresso

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. 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

Para observar informações de progresso, use os métodos getWorkInfoById e receba uma referência a WorkInfo.

Confira um exemplo que usa getWorkInfoByIdFlow para Kotlin e getWorkInfoByIdLiveData para Java.

Kotlin

WorkManager.getInstance(applicationContext)
      // requestId is the WorkRequest id
      .getWorkInfoByIdFlow(requestId)
      .collect { 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. Para saber como receber o stopReason quando o trabalho é encerrado inesperadamente, consulte Observar o estado do motivo da interrupção.