O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Definir solicitações de trabalho

O guia de primeiros passos abordou como criar um WorkRequest simples e enfileirá-lo.

Neste guia, você aprenderá a definir e personalizar objetos WorkRequest para lidar com casos de uso comuns, por exemplo:

  • Programar trabalhos únicos e recorrentes
  • Definir restrições de trabalho, como exigir Wi-Fi ou carregamento
  • Garantir um atraso mínimo na execução de trabalhos
  • Definir estratégias de novas tentativas e espera
  • Transmitir dados de entrada para os trabalhos
  • Agrupar trabalhos relacionados usando tags

Geral

O trabalho é definido no WorkManager por meio de uma WorkRequest. Para programar qualquer trabalho com o WorkManager, é preciso primeiro criar um objeto WorkRequest e depois colocá-lo em fila.

Kotlin


val myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest)

Java


WorkRequest myWorkRequest = ...
WorkManager.getInstance(myContext).enqueue(myWorkRequest);

O objeto WorkRequest contém todas as informações necessárias para o WorkManager programar e executar seu trabalho. Isso inclui restrições que precisam ser atendidas para que seu trabalho seja executado, programação de informações como atrasos ou intervalos de repetição e configuração de novas tentativas, podendo incluir também dados de entrada caso seu trabalho dependa deles.

WorkRequest é uma classe básica abstrata. Há duas implementações derivadas dessa classe que podem ser usadas para criar a solicitação, OneTimeWorkRequest e PeriodicWorkRequest. Como os nomes indicam, OneTimeWorkRequest é útil para programar um trabalho não recorrente, enquanto PeriodicWorkRequest é mais apropriada para programar um trabalho que se repete em algum intervalo.

Programar trabalho único

Para trabalhos simples, que não requerem configuração adicional, use o método estático from:

Kotlin


val myWorkRequest = OneTimeWorkRequest.from(MyWork::class.java)

Java


WorkRequest myWorkRequest = OneTimeWorkRequest.from(MyWork.class);

Para trabalhos mais complexos, use um builder.

Kotlin


val uploadWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       // Additional configuration
       .build()

Java


WorkRequest uploadWorkRequest =
   new OneTimeWorkRequest.Builder(MyWork.class)
       // Additional configuration
       .build();

Programar trabalho periódico

Às vezes, seu app pode exigir que determinados trabalhos sejam executados periodicamente. Por exemplo, pode ser que você queira fazer backup dos seus dados, fazer o download de novos conteúdos no seu app ou fazer upload de registros para um servidor periodicamente.

Veja como usar a PeriodicWorkRequest para criar um objeto WorkRequest que é executado periodicamente:

Kotlin


val saveRequest =
       PeriodicWorkRequestBuilder<SaveImageToFileWorker>(1, TimeUnit.HOURS)
    // Additional configuration
           .build()

Java


PeriodicWorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class, 1, TimeUnit.HOURS)
           // Constraints
           .build();

Neste exemplo, o trabalho é programado com um intervalo de uma hora.

O período é definido como o tempo mínimo entre repetições. O momento exato em que o worker será executado depende das restrições usadas no objeto WorkRequest e das otimizações feitas pelo sistema.

Intervalos de execução flexíveis

Se a natureza do trabalho torna necessário definir o tempo de execução, é possível configurar a PeriodicWorkRequest para ser executada dentro de um período flexível em de cada período de intervalo, conforme mostrado na Figura 1.

É possível definir um intervalo flexível para um job periódico. Defina um intervalo de repetição e um intervalo flexível que especifique determinado período no final do intervalo de repetição. O WorkManager tenta executar o job em algum momento do intervalo flexível em cada ciclo.

Figura 1. O diagrama mostra intervalos de repetição com o período flexível em que o trabalho pode ser executado.

Para definir o trabalho periódico com um período flexível, transmita um flexInterval junto ao repeatInterval ao criar a PeriodicWorkRequest. O período flexível começa às repeatInterval - flexInterval e dura até o fim do intervalo.

Veja a seguir um exemplo de trabalho periódico que pode ser executado nos últimos 15 minutos de cada período de uma hora.

Kotlin


val myUploadWork = PeriodicWorkRequestBuilder<SaveImageToFileWorker>(
       1, TimeUnit.HOURS, // repeatInterval (the period cycle)
       15, TimeUnit.MINUTES) // flexInterval
    .build()

Java


WorkRequest saveRequest =
       new PeriodicWorkRequest.Builder(SaveImageToFileWorker.class,
               1, TimeUnit.HOURS,
               15, TimeUnit.MINUTES)
           .build();

O intervalo de repetição precisa ser maior ou igual a PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS, e o intervalo flexível precisa ser maior ou igual a PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS.

Efeito das restrições no trabalho periódico

Você pode aplicar restrições ao trabalho periódico. Por exemplo, é possível adicionar uma restrição à solicitação de trabalho para que ele seja executado apenas quando o dispositivo do usuário estiver sendo carregado. Nesse caso, mesmo que o intervalo de repetição definido seja transmitido, a PeriodicWorkRequest não será executada até que essa condição seja atendida. Isso pode atrasar uma execução específica do seu trabalho ou até mesmo ignorá-lo caso as condições não sejam atendidas no intervalo de execução.

Restrições de trabalho

As restrições garantem que o trabalho seja adiado até que as condições ideais sejam atendidas. As restrições a seguir estão disponíveis para o WorkManager.

NetworkType Restringe o tipo de rede necessário para que o trabalho seja executado. Por exemplo, Wi-Fi (UNMETERED).
BatteryNotLow Quando definida como "true", seu trabalho não será executado se o dispositivo estiver no modo de bateria fraca.
RequiresCharging Quando definida como "true", seu trabalho só será executado quando o dispositivo estiver sendo carregado.
DeviceIdle Quando definida como "true", o dispositivo do usuário precisará ficar inativo antes da execução do trabalho. Isso pode ser útil para executar operações em lote que podem ter um impacto negativo no desempenho de outros apps executados ativamente no dispositivo do usuário.
StorageNotLow Quando definida como "true", seu trabalho não será executado se o espaço de armazenamento do usuário no dispositivo estiver baixo demais.

Para criar um conjunto de restrições e associá-lo a algum trabalho, crie uma instância de Constraints usando o Contraints.Builder() e atribua-a ao WorkRequest.Builder().

Por exemplo, o código a seguir cria uma solicitação de trabalho que só é executada quando o dispositivo do usuário está sendo carregado e está usando o Wi-Fi:

Kotlin


val constraints = Constraints.Builder()
   .setRequiredNetworkType(NetworkType.UNMETERED)
   .setRequiresCharging(true)
   .build()

val myWorkRequest: WorkRequest =
   OneTimeWorkRequestBuilder<MyWork>()
       .setConstraints(constraints)
       .build()

Java


Constraints constraints = new Constraints.Builder()
       .setRequiredNetworkType(NetworkType.UNMETERED)
       .setRequiresCharging(true)
       .build();

WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setConstraints(constraints)
               .build();

Quando várias restrições forem especificadas, o trabalho será executado somente quando todas elas forem atendidas.

Se uma restrição não seja atendida enquanto o trabalho estiver em execução, o WorkManager interromperá o worker. O trabalho será executado novamente quando todas as restrições forem atendidas.

Trabalho atrasado

Se o trabalho não tiver restrições ou se todas as restrições forem atendidas quando o trabalho for colocado em fila, o sistema poderá executá-lo imediatamente. Se você não quiser que o trabalho seja executado imediatamente, especifique um atraso inicial mínimo.

Veja um exemplo de como configurar seu trabalho para ser executado pelo menos 10 minutos depois de ser colocado em fila.

Kotlin


val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .setInitialDelay(10, TimeUnit.MINUTES)
   .build()

Java


WorkRequest myWorkRequest =
      new OneTimeWorkRequest.Builder(MyWork.class)
               .setInitialDelay(10, TimeUnit.MINUTES)
               .build();

O exemplo ilustra como definir um atraso inicial para uma OneTimeWorkRequest, mas também é possível definir um atraso inicial para uma PeriodicWorkRequest. Nesse caso, somente a primeira execução do seu trabalho periódico será atrasada.

Política de nova tentativa e espera

Se você precisar que o WorkManager tente realizar o trabalho novamente, poderá retornar Result.retry() do worker. Seu trabalho é reprogramado de acordo com um atraso de espera e uma política de espera.

  • O atraso de espera especifica o tempo mínimo que é necessário aguardar antes de tentar executar o trabalho novamente após a primeira tentativa. Esse valor não pode ser inferior a 10 segundos (ou MIN_BACKOFF_MILLIS).

  • A política de espera define como o atraso de espera aumentará ao longo do tempo para novas tentativas subsequentes. O WorkManager é compatível com duas políticas de espera, LINEAR e EXPONENTIAL.

Cada solicitação de trabalho tem uma política de espera e um atraso de espera. A política padrão é EXPONENTIAL com um atraso de 10 segundos, mas você pode modificar essa configuração na configuração da solicitação de trabalho.

Veja um exemplo de personalização do atraso e da política de espera.

Kotlin


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

Java


WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
               .setBackoffCriteria(
                       BackoffPolicy.LINEAR,
                       OneTimeWorkRequest.MIN_BACKOFF_MILLIS,
                       TimeUnit.MILLISECONDS)
               .build();

Nesse exemplo, o atraso de espera mínimo é definido como o valor mínimo permitido, 10 segundos. Como a política é LINEAR, o intervalo de repetição aumentará aproximadamente 10 segundos a cada nova tentativa. Por exemplo, a primeira execução terminada com Result.retry() será tentada novamente após 10 segundos, seguida por 20, 30, 40 e assim por diante se o trabalho continuar a retornar Result.retry() após tentativas subsequentes. Se a política de espera fosse definida como EXPONENTIAL, a sequência de duração da nova tentativa seria mais próxima de 20, 40, 80 e assim por diante.

Incluir tag no trabalho

Cada solicitação de trabalho tem um identificador exclusivo que pode ser usado para identificá-la posteriormente e cancelar o trabalho ou observar o progresso.

Se você tem um grupo de trabalhos logicamente relacionados, também pode ser útil marcar esses itens de trabalho. A inclusão de tags permite que você opere com um grupo de solicitações de trabalho.

Por exemplo, WorkManager.cancelAllWorkByTag(String) cancela todas as solicitações de trabalho com uma tag específica, e WorkManager.getWorkInfosByTag(String) retorna uma lista dos objetos WorkInfo que podem ser usados para determinar o estado de trabalho atual.

O código a seguir mostra como adicionar uma tag de "limpeza" ao seu trabalho:

Kotlin


val myWorkRequest = OneTimeWorkRequestBuilder<MyWork>()
   .addTag("cleanup")
   .build()

Java


WorkRequest myWorkRequest =
       new OneTimeWorkRequest.Builder(MyWork.class)
       .addTag("cleanup")
       .build();

Por fim, várias tags podem ser adicionadas a uma única solicitação de trabalho. Internamente, essas tags são armazenadas como um conjunto de strings. A partir de uma solicitação de trabalho, você recupera o conjunto de tags por meio de WorkRequest.getTags().

Atribuir dados de entrada

Seu trabalho pode exigir dados de entrada para que seja realizado. Por exemplo, trabalhos que processam o upload de uma imagem podem exigir que o URI da imagem seja enviado por upload como entrada.

Os valores de entrada são armazenados como pares de chave-valor em um objeto Data e podem ser definidos na solicitação de trabalho. O WorkManager entregará a entrada Data para seu trabalho ao executá-lo. A classe Worker pode acessar os argumentos de entrada chamando Worker.getInputData(). O código abaixo mostra como criar uma instância de Worker que requer dados de entrada e como enviá-la na solicitação de trabalho.

Kotlin


// Define the Worker requiring input
class UploadWork(appContext: Context, workerParams: WorkerParameters)
   : Worker(appContext, workerParams) {

   override fun doWork(): Result {
       val imageUriInput =
           inputData.getString("IMAGE_URI") ?: return Result.failure()

       uploadFile(imageUriInput)
       return Result.success()
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
val myUploadWork = OneTimeWorkRequestBuilder<UploadWork>()
   .setInputData(workDataOf(
       "IMAGE_URI" to "http://..."
   ))
   .build()

Java


// Define the Worker requiring input
public class UploadWork extends Worker {

   public UploadWork(Context appContext, WorkerParameters workerParams) {
       super(appContext, workerParams);
   }

   @NonNull
   @Override
   public Result doWork() {
       String imageUriInput = getInputData().getString("IMAGE_URI");
       if(imageUriInput == null) {
           return Result.failure();
       }

       uploadFile(imageUriInput);
       return Result.success();
   }
   ...
}

// Create a WorkRequest for your Worker and sending it input
WorkRequest myUploadWork =
      new OneTimeWorkRequest.Builder(UploadWork.class)
           .setInputData(
               new Data.Builder()
                   .putString("IMAGE_URI", "http://...")
                   .build()
           )
           .build();

Da mesma forma, a classe Data pode ser usada para gerar um valor de retorno. Os dados de entrada e saída são abordados com mais detalhes na seção Parâmetros de entrada e valores retornados.

Próximas etapas

Na página Estados e observação, você aprenderá mais sobre estados de trabalho e como monitorar o progresso do seu trabalho.