O WorkManager permite que você atualize um WorkRequest
depois de já
tê-lo colocado na fila. Muitas vezes, isso é 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()
é a forma de fazer isso.
O método updateWork()
permite que você altere determinados aspectos de um
WorkRequest
rapidamente, sem ter que passar pelo processo de cancelamento
manual e enfileiramento de um novo. Isso simplifica muito o processo de
desenvolvimento.
Evitar cancelar o trabalho
Em geral, evite cancelar uma WorkRequest existente e colocar uma nova na fila. Isso pode fazer o app repetir determinadas tarefas e exigir que você programe uma quantidade significativa de código extra.
Considere os seguintes exemplos de onde 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, vai ser necessário calcular um ajuste para garantir que o novo ambiente de execução esteja alinhado à 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 enfileirar uma nova solicitação.
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 status de trabalho
Imagine um app de fotos que faz backup diário das fotos do usuário. Para isso,
uma PeriodicWorkRequest
foi colocada na fila. A WorkRequest
tem restrições
que exigem que o dispositivo esteja carregando e conectado ao Wi-Fi.
No entanto, o usuário carrega o dispositivo apenas por 20 minutos por dia usando um carregador
rápido. Nesse caso, o app pode atualizar o WorkRequest
para relaxar a
restrição de carregamento e conseguir fazer upload das fotos mesmo que o dispositivo
não esteja totalmente carregado.
Nessa situação, você pode usar 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
existente, sem precisar cancelar e enfileirar um novo.
Para atualizar um trabalho na fila, siga estas etapas:
- Conseguir o ID existente para um trabalho na fila: extraia 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 extraí-lo mais tarde 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 que corresponda aoWorkRequest
existente. - Definir restrições: use
WorkRequest.Builder.setConstraints()
para transmitir as novas restrições do 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 vários valores que descrevem se o
WorkManager conseguiu ou não aplicar as mudanças. Também indica quando foi
possível aplicar a alteração.
Para mais informações, consulte a referência updateWork()
e UpdateResult
.
Rastreie 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 recuperar uma instância deWorkInfo
correspondente ao seuWorkRequest
.- É 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 deWorkRequest
.- 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 um
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()
.