O WorkManager permite que você atualize um WorkRequest
depois de o
enfileirar. Isso geralmente é necessário em apps maiores que mudam
restrições com frequência ou precisam atualizar os workers em tempo real. A partir do WorkManager
versão 2.8.0, a API updateWork()
é o meio para fazer isso.
O método updateWork()
permite que você altere determinados aspectos de um
WorkRequest
imediatamente, sem precisar passar pelo processo de cancelamento
e enfileiramento de um novo manualmente. Isso simplifica muito o processo
de desenvolvimento.
Evite cancelar o trabalho
Em geral, evite cancelar um WorkRequest existente e colocar um novo na fila. Isso pode fazer com que o app repita algumas tarefas e exigir que você escreva uma quantidade significativa de código extra.
Considere os exemplos abaixo em que o cancelamento de uma WorkRequest pode causar dificuldades:
- Solicitação de back-end: se você cancelar um
Worker
enquanto estiver computando um payload para enviar ao servidor, o novoWorker
precisará ser reiniciado e recalcular o payload potencialmente caro. - Programação:se você cancelar um
PeriodicWorkRequest
e quiser que o novoPeriodicWorkRequest
seja executado na mesma programação, será necessário calcular um ajuste de horário para garantir que o novo ambiente de execução esteja alinhado com a solicitação de trabalho anterior.
A API updateWork()
permite atualizar as restrições de uma solicitação de trabalho e
outros parâmetros sem o problema de cancelar e colocar uma nova solicitação na fila.
Quando cancelar um trabalho
Há casos em que é necessário cancelar diretamente um WorkRequest
em vez de
chamar updateWork()
. Isso é o que você precisa fazer quando quiser alterar a
natureza fundamental do trabalho que colocou em fila.
Quando atualizar o perfil de trabalho
Imagine um app de fotos que faz backup diário das fotos do usuário. Ela
colocou um PeriodicWorkRequest
na fila para fazer isso, já que o WorkRequest
tem restrições
que exigem que o dispositivo esteja carregando e conectado ao Wi-Fi.
No entanto, o usuário só carrega o dispositivo por 20 minutos por dia em um carregador
rápido. Nesse caso, o app pode atualizar a WorkRequest
para relaxar a
restrição de carregamento e ainda poder fazer upload das fotos mesmo que o dispositivo
não esteja totalmente carregado.
Nessa situação, use o método updateWork()
para atualizar as restrições da solicitação
de trabalho.
Como atualizar o perfil de trabalho
O método updateWork()
oferece uma maneira simples de atualizar um
WorkRequest
já existente, sem precisar cancelar e colocar um novo em fila.
Para atualizar um trabalho na fila, siga estas etapas:
- Acessar o ID do trabalho na fila: acesse o ID da WorkRequest que você
quer atualizar. É possível extrair esse ID com qualquer uma das
APIs
getWorkInfo
ou mantendo o ID do WorkRequest inicial para ser recuperado depois com a propriedade públicaWorkRequest.id
antes de colocá-lo na fila. - Criar nova WorkRequest: crie uma nova
WorkRequest
e useWorkRequest.Builder.setID()
para definir o ID dela que corresponde ao daWorkRequest
existente. - Definir restrições: use
WorkRequest.Builder.setConstraints()
para transmitir novas restrições ao WorkManager. - Chamar updateWork: transmita a nova WorkRequest para
updateWork()
.
Exemplo de atualização de trabalho
Confira um exemplo de snippet de código em Kotlin que demonstra como usar o
método updateWork()
para mudar as restrições de bateria de um WorkRequest
usado
para fazer upload de fotos:
suspend fun updatePhotoUploadWork() {
// Get instance of WorkManager.
val workManager = WorkManager.getInstance(context)
// Retrieve the work request ID. In this example, the work being updated is unique
// work so we can retrieve the ID using the unique work name.
val photoUploadWorkInfoList = workManager.getWorkInfosForUniqueWork(
PHOTO_UPLOAD_WORK_NAME
).await()
val existingWorkRequestId = photoUploadWorkInfoList.firstOrNull()?.id ?: return
// Update the constraints of the WorkRequest to not require a charging device.
val newConstraints = Constraints.Builder()
// Add other constraints as required here.
.setRequiresCharging(false)
.build()
// Create new WorkRequest from existing Worker, new constraints, and the id of the old WorkRequest.
val updatedWorkRequest: WorkRequest =
OneTimeWorkRequestBuilder<MyWorker>()
.setConstraints(newConstraints)
.setId(existingWorkRequestId)
.build()
// Pass the new WorkRequest to updateWork().
workManager.updateWork(updatedWorkRequest)
}
Processar o resultado
updateWork()
retorna um ListenableFuture<UpdateResult>
. O UpdateResult
fornecido pode ter um dos diversos valores que descrevem se o
WorkManager conseguiu ou não aplicar as mudanças. Ele também indica quando foi
possível aplicar a alteração.
Para mais informações, consulte a referência updateWork()
e UpdateResult
.
Monitore o trabalho com gerações
Cada vez que você atualiza um WorkRequest
, a geração dele aumenta em um. Isso
permite que você rastreie exatamente qual WorkRequest
está na fila.
As gerações oferecem mais controle ao observar, rastrear e testar solicitações de
trabalho.
Para conseguir a geração de um WorkRequest
, siga estas etapas:
- WorkInfo: chame
WorkManager.getWorkInfoById()
para extrair uma instância deWorkInfo
correspondente àWorkRequest
.- É possível chamar um dos vários métodos que retornam um
WorkInfo
. Para saber mais, consulte a referência do WorkManager.
- É possível chamar um dos vários métodos que retornam um
- getGeneration: chame
getGeneration()
na instância deWorkInfo
. OInt
retornado corresponde à geração doWorkRequest
.- Não há um campo ou uma propriedade de geração, apenas o
método
WorkInfo.getGeneration()
.
- Não há um campo ou uma propriedade de geração, apenas o
método
Exemplo de geração de faixas
Confira abaixo um exemplo de implementação do fluxo de trabalho descrito acima para
recuperar a geração de um WorkRequest
.
// Get instance of WorkManager.
val workManager = WorkManager.getInstance(context)
// Retrieve WorkInfo instance.
val workInfo = workManager.getWorkInfoById(oldWorkRequestId)
// Call getGeneration to retrieve the generation.
val generation = workInfo.getGeneration()
Políticas para atualizar o trabalho
Anteriormente, a solução recomendada para atualizar o trabalho periódico era enfileirar uma
PeriodicWorkRequest
com a política ExistingPeriodicWorkPolicy.REPLACE
.
Se houvesse um PeriodicWorkRequest
pendente com o mesmo id
exclusivo, a nova
solicitação de trabalho seria cancelado e excluído. Esta política foi descontinuada e
substituída pelo fluxo de trabalho que usa ExistingPeriodicWorkPolicy.UPDATE
.
Por exemplo, ao usar enqueueUniquePeriodicWork
com um
PeriodicWorkRequest
, você pode inicializar o novo PeriodicWorkRequest
com a
política ExistingPeriodicWorkPolicy.UPDATE
. Se houver um PeriodicWorkRequest
pendente com o mesmo nome exclusivo, o WorkManager o atualizará para a
nova especificação. Seguindo esse fluxo de trabalho, não é necessário usar
updateWork()
.