Este codelab faz parte do curso Conceitos básicos do Kotlin para Android. Você aproveitará mais o curso se fizer os codelabs em sequência. Todos os codelabs do curso estão listados na página de destino dos codelabs do curso Conceitos básicos do Kotlin para Android.
Introdução
A maioria dos apps reais precisa executar tarefas em segundo plano de longa duração. Por exemplo, um app pode fazer upload de arquivos para um servidor, sincronizar dados de um servidor e salvá-los em um banco de dados Room
, enviar registros para um servidor ou executar operações caras nos dados. Essas operações precisam ser realizadas em segundo plano, fora da linha de execução de IU (linha de execução principal). As tarefas em segundo plano consomem recursos limitados do dispositivo, como a RAM e a bateria. Se isso não for feito corretamente, pode resultar em uma experiência ruim para o usuário.
Neste codelab, você aprenderá a usar o WorkManager
para programar uma tarefa em segundo plano de maneira otimizada e eficiente. Para saber mais sobre outras soluções disponíveis para processamento em segundo plano no Android, consulte Guia para o processamento em segundo plano.
O que você já precisa saber
- Como usar os Componentes da arquitetura do Android
ViewModel
,LiveData
eRoom
. - Como fazer transformações em uma classe
LiveData
. - Como criar e iniciar uma corrotina.
- Como usar adaptadores de vinculação na vinculação de dados.
- Como carregar dados em cache usando um padrão de repositório.
O que você vai aprender
- Como criar um
Worker
, que representa uma unidade de trabalho. - Como criar um
WorkRequest
para solicitar o trabalho a ser realizado. - Como adicionar restrições ao
WorkRequest
para definir como e quando um worker será executado. - Como usar o
WorkManager
para programar tarefas em segundo plano.
Atividades do laboratório
- Crie um worker para executar uma tarefa em segundo plano e fazer a pré-busca da playlist de vídeos DevBytes na rede.
- Programe a execução do worker periodicamente.
- Adicione restrições à
WorkRequest
. - Programe uma
WorkRequest
periódica que é executada uma vez por dia.
Neste codelab, você trabalhará no app DevBytes que desenvolveu em um codelab anterior. Se você não tem esse app, faça o download do código inicial para esta lição.
O app DevBytes exibe uma lista de vídeos DevByte, que são tutoriais curtos feitos pela equipe de relações com desenvolvedores Google Android. Os vídeos apresentam recursos para desenvolvedores e práticas recomendadas para o desenvolvimento em Android.
Para melhorar a experiência do usuário no app, faça uma pré-busca dos vídeos uma vez por dia. Isso garante que o usuário receba o conteúdo atualizado assim que abrir o app.
Nesta tarefa, você fará o download e inspecionará o código inicial.
Etapa 1: fazer o download e executar o app inicial
Você pode continuar trabalhando no app DevBytes que criou no codelab anterior (se tiver). Se preferir, faça o download do app inicial.
Nesta tarefa, você fará o download e executará o app inicial, além de examinar o código dele.
- Se você ainda não tem o app DevBytes, faça o download do código inicial DevBytes para este codelab no projeto DevBytesRepository do GitHub.
- Descompacte o código e abra o projeto no Android Studio.
- Conecte o dispositivo ou emulador de teste à Internet, se ainda não estiver conectado. Crie e execute o app. Ele busca a lista de vídeos DevByte da rede e os exibe.
- Toque em qualquer vídeo para abri-lo no app YouTube.
Etapa 2: analisar o código
O app inicial tem vários códigos que foram introduzidos no codelab anterior. O código inicial deste codelab tem módulos de rede, interface do usuário, cache off-line e repositório. Para se concentrar na programação da tarefa em segundo plano, use WorkManager
.
- No Android Studio, expanda todos os pacotes.
- Conheça o pacote
database
. O pacote contém as entidades de banco de dados e o banco de dados local, que está implementado usandoRoom
. - Conheça o pacote
repository
. O pacote contém a classeVideosRepository
que abstrai a camada de dados do restante do app. - Explore o restante do código inicial por conta própria e com a ajuda do codelab anterior.
O WorkManager
é um dos Componentes da arquitetura do Android e faz parte do Android Jetpack. WorkManager
é para trabalho em segundo plano que pode ser adiado e requer execução garantida:
- Adiável significa que o trabalho não é necessário para ser executado imediatamente. Por exemplo, o envio de dados de análise ao servidor ou a sincronização do banco de dados em segundo plano é um trabalho que pode ser adiado.
- Execução garantida significa que a tarefa será executada mesmo que o app seja fechado ou o dispositivo seja reiniciado.
Enquanto o WorkManager
executa o trabalho em segundo plano, ele cuida dos problemas de compatibilidade e das práticas recomendadas de integridade da bateria e do sistema. WorkManager
oferece compatibilidade com o nível 14 da API. WorkManager
escolhe uma maneira adequada de programar uma tarefa em segundo plano, dependendo do nível da API do dispositivo. Ele pode usar JobScheduler
(na API 23 e versões mais recentes) ou uma combinação de AlarmManager
e BroadcastReceiver
.
WorkManager
também permite definir critérios sobre quando a tarefa em segundo plano é executada. Por exemplo, talvez você queira que a tarefa seja executada somente quando o status da bateria, o status da rede ou o estado de carga atenderem a determinados critérios. Você aprenderá a definir restrições mais adiante neste codelab.
Neste codelab, você programa uma tarefa para fazer a pré-busca da playlist de vídeos DevBytes da rede uma vez por dia. Para programar esta tarefa, use a biblioteca WorkManager
.
- Abra o arquivo
build.gradle (Module:app)
e adicione a dependênciaWorkManager
ao projeto.
Se você usar a versão mais recente da biblioteca, o app da solução será compilado como esperado. Se isso não acontecer, tente resolver o problema ou reverta para a versão da biblioteca mostrada abaixo.
// WorkManager dependency
def work_version = "1.0.1"
implementation "android.arch.work:work-runtime-ktx:$work_version"
- Sincronize seu projeto e confira se não há erros de compilação.
Antes de adicionar o código ao projeto, conheça as seguintes classes na biblioteca WorkManager
:
Worker
Nesta classe, você define o trabalho (a tarefa) a ser executado em segundo plano. Você estenderá essa classe e substituirá o métododoWork()
. O métododoWork()
é onde você coloca o código que será executado em segundo plano, como ao sincronizar dados com o servidor ou processar imagens. Implemente oWorker
nessa tarefa.WorkRequest
Essa classe representa uma solicitação para executar o worker em segundo plano. Use oWorkRequest
para configurar como e quando executar a tarefa do worker, com a ajuda doConstraints
, como o dispositivo conectado ou o Wi-Fi. Você implementará oWorkRequest
em uma tarefa posterior.WorkManager
Esta classe programa e executa seuWorkRequest
. OWorkManager
programa as solicitações de trabalho de modo a distribuir a carga nos recursos do sistema, respeitando as restrições especificadas. Você implementará oWorkManager
em uma tarefa posterior.
Etapa 1: criar um worker
Nesta tarefa, você adicionará um Worker
para fazer a pré-busca da playlist de vídeos DevBytes em segundo plano.
- No pacote
devbyteviewer
, crie um novo pacote com o nomework
. - No pacote
work
, crie uma nova classe do Kotlin com o nomeRefreshDataWorker
. - Estenda a classe
RefreshDataWorker
daCoroutineWorker
. Transmitacontext
eWorkerParameters
como parâmetros do construtor.
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
}
- Para resolver o erro de classe abstrata, substitua o método
doWork()
na classeRefreshDataWorker
.
override suspend fun doWork(): Result {
return Result.success()
}
Uma função de suspensão é uma função que pode ser pausada e retomada mais tarde. Uma função de suspensão pode executar uma operação de longa duração e aguardar a conclusão sem bloquear a linha de execução principal.
Etapa 2: implementar doWork()
O método doWork()
dentro da classe Worker
é chamado em uma linha de execução em segundo plano. O método executa o trabalho de forma síncrona e precisa retornar um objeto ListenableWorker.Result
. O sistema Android oferece um Worker
no máximo 10 minutos para concluir a execução e retornar um objeto ListenableWorker.Result
. Após esse período, o sistema forçará o fechamento de Worker
.
Para criar um objeto ListenableWorker.Result
, chame um dos seguintes métodos estáticos para indicar o status de conclusão do trabalho em segundo plano:
Result.success()
: trabalho concluído.Result.failure()
: trabalho concluído com uma falha permanente.Result.retry()
: o trabalho encontrou uma falha temporária e precisa ser repetido.
Nesta tarefa, você implementará o método doWork()
para buscar a playlist de vídeos DevBytes da rede. É possível reutilizar os métodos existentes na classe VideosRepository
para recuperar os dados da rede.
- Na classe
RefreshDataWorker
, emdoWork()
, crie e instancie um objetoVideosDatabase
e um objetoVideosRepository
.
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
return Result.success()
}
- Na classe
RefreshDataWorker
, no métododoWork()
, acima da instruçãoreturn
, chame o métodorefreshVideos()
dentro de um blocotry
. Adicione um registro para monitorar quando o worker é executado.
try {
repository.refreshVideos( )
Timber.d("Work request for sync is run")
} catch (e: HttpException) {
return Result.retry()
}
Para resolver o erro "Referência não resolvida", importe retrofit2.HttpException
.
- Veja a classe
RefreshDataWorker
completa para sua referência:
class RefreshDataWorker(appContext: Context, params: WorkerParameters) :
CoroutineWorker(appContext, params) {
override suspend fun doWork(): Result {
val database = getDatabase(applicationContext)
val repository = VideosRepository(database)
try {
repository.refreshVideos()
} catch (e: HttpException) {
return Result.retry()
}
return Result.success()
}
}
Uma Worker
define uma unidade de trabalho, e o WorkRequest
define como e quando o trabalho será executado. Há duas implementações concretas da classe WorkRequest
:
- A classe
OneTimeWorkRequest
é destinada a tarefas que só ocorrem uma vez. Uma tarefa única acontece apenas uma vez. - A classe
PeriodicWorkRequest
é destinada a trabalhos periódicos, tarefas que se repetem a cada intervalo.
As tarefas podem ser pontuais ou periódicas, portanto, escolha a classe de acordo. Para ver mais informações sobre como programar trabalhos recorrentes, consulte a documentação sobre trabalhos recorrentes.
Nesta tarefa, você vai definir e programar um WorkRequest
para executar o worker criado na tarefa anterior.
Etapa 1: configurar trabalhos recorrentes
Em um app Android, a classe Application
é a classe base que contém todos os outros componentes, como atividades e serviços. Quando o processo do aplicativo ou pacote é criado, a classe Application
(ou qualquer subclasse de Application
) é instanciada antes de qualquer outra classe.
Neste app de exemplo, a classe DevByteApplication
é uma subclasse da Application
. A classe DevByteApplication
é um bom lugar para programar a WorkManager
.
- Na classe
DevByteApplication
, crie um método com o nomesetupRecurringWork()
para configurar o trabalho em segundo plano recorrente.
/**
* Setup WorkManager background job to 'fetch' new network data daily.
*/
private fun setupRecurringWork() {
}
- No método
setupRecurringWork()
, crie e inicialize uma solicitação de trabalho periódica para ser executada uma vez por dia, usando o métodoPeriodicWorkRequestBuilder()
. Transmita a classeRefreshDataWorker
que você criou na tarefa anterior. Transmita um intervalo de repetição de1
com uma unidade de tempo deTimeUnit.
DAYS
.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.build()
Para resolver o erro, importe java.util.concurrent.TimeUnit
.
Etapa 2: programar uma WorkRequest com o WorkManager
Depois de definir o WorkRequest
, programe-o com WorkManager
usando o método enqueueUniquePeriodicWork()
. Esse método permite adicionar um PeriodicWorkRequest
com o nome exclusivo à fila, em que apenas um PeriodicWorkRequest
de um determinado nome pode estar ativo por vez.
Por exemplo, talvez você queira que apenas uma operação de sincronização esteja ativa. Se uma operação de sincronização estiver pendente, você poderá permitir que ela seja executada ou substituída com o novo trabalho, usando uma ExistingPeriodicWorkPolicy.
Para saber mais sobre como programar um WorkRequest
, consulte a documentação do WorkManager
.
- Na classe
RefreshDataWorker
, adicione um objeto complementar no início da classe. Defina um nome de trabalho para identificar esse worker com exclusividade.
companion object {
const val WORK_NAME = "com.example.android.devbyteviewer.work.RefreshDataWorker"
}
- Na classe
DevByteApplication
, no final do métodosetupRecurringWork()
, programe o trabalho usando o métodoenqueueUniquePeriodicWork()
. Transmita a enumeraçãoKEEP
para a ExistingPeriodicWorkPolicy. TransmitarepeatingRequest
como o parâmetroPeriodicWorkRequest
.
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
Se houver um trabalho pendente (não concluído) com o mesmo nome, o parâmetro ExistingPeriodicWorkPolicy.
KEEP
fará com que o WorkManager
mantenha o trabalho periódico anterior e descarte a nova solicitação de trabalho.
- No início da classe
DevByteApplication
, crie um objetoCoroutineScope
. TransmitaDispatchers.Default
como o parâmetro do construtor.
private val applicationScope = CoroutineScope(Dispatchers.Default)
- Na classe
DevByteApplication
, adicione um novo método com o nomedelayedInit()
para iniciar uma corrotina.
private fun delayedInit() {
applicationScope.launch {
}
}
- No método
delayedInit()
, chamesetupRecurringWork()
. - Mova a inicialização do Timber do método
onCreate()
para o métododelayedInit()
.
private fun delayedInit() {
applicationScope.launch {
Timber.plant(Timber.DebugTree())
setupRecurringWork()
}
}
- Na classe
DevByteApplication
, no final do métodoonCreate()
, adicione uma chamada para o métododelayedInit()
.
override fun onCreate() {
super.onCreate()
delayedInit()
}
- Abra o painel Logcat na parte inferior da janela do Android Studio. Filtrar em
RefreshDataWorker
. - Execute o app. O
WorkManager
programa seu trabalho recorrente imediatamente.
No painel Logcat, observe os log statements que mostram que a solicitação de trabalho está programada e é executada corretamente.
D/RefreshDataWorker: Work request for sync is run I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
Como o registro WM-WorkerWrapper
é exibido na biblioteca WorkManager
, não é possível alterar essa mensagem de registro.
Etapa 3: (opcional) programar a WorkRequest para um intervalo mínimo
Nesta etapa, você reduz o intervalo de tempo de 1 dia para 15 minutos. Isso é feito para que você possa ver os registros de uma solicitação de trabalho periódica em ação.
- Na classe
DevByteApplication
, no métodosetupRecurringWork()
, comente a definição atual dorepeatingRequest
. Adicione uma nova solicitação de trabalho com um intervalo de repetição periódico de15
minutos.
// val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
// .build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.build()
- Abra o painel Logcat no Android Studio e filtre por
RefreshDataWorker
. Para limpar os registros anteriores, clique no ícone Clear logcat..
- Execute o app, e o
WorkManager
programa seu trabalho recorrente imediatamente. No painel Logcat, observe os registros. A solicitação de trabalho é executada uma vez a cada 15 minutos. Aguarde 15 minutos para ver outro conjunto de registros de solicitação de trabalho. Você pode deixar o app em execução ou fechá-lo. O gerenciador de trabalho ainda deverá ser executado.
Observe que o intervalo pode ser inferior a 15 minutos e, às vezes, mais de 15 minutos. A duração exata está sujeita às otimizações de bateria do SO.
12:44:40 D/RefreshDataWorker: Work request for sync is run 12:44:40 I/WM-WorkerWrapper: Worker result SUCCESS for Work 12:59:24 D/RefreshDataWorker: Work request for sync is run 12:59:24 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:15:03 D/RefreshDataWorker: Work request for sync is run 13:15:03 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:29:22 D/RefreshDataWorker: Work request for sync is run 13:29:22 I/WM-WorkerWrapper: Worker result SUCCESS for Work 13:44:26 D/RefreshDataWorker: Work request for sync is run 13:44:26 I/WM-WorkerWrapper: Worker result SUCCESS for Work
Parabéns! Você criou um worker e programou a solicitação de trabalho com WorkManager
. No entanto, há um problema: você não especificou restrições. WorkManager
programará o trabalho uma vez por dia, mesmo que o dispositivo esteja com pouca bateria, suspenso ou sem conexão de rede. Isso afetará a bateria e o desempenho do dispositivo e resultará em uma experiência insatisfatória para o usuário.
Na próxima tarefa, você vai adicionar uma restrição para resolver esse problema.
Na tarefa anterior, você usou o WorkManager
para programar uma solicitação de trabalho. Nesta tarefa, você adicionará critérios para quando executar o trabalho.
Ao definir o WorkRequest
, você pode especificar restrições para quando o Worker
será executado. Por exemplo, é possível especificar que o trabalho seja executado somente quando o dispositivo estiver ocioso ou apenas quando ele estiver conectado e conectado ao Wi-Fi. Também é possível especificar uma política de espera para repetir o trabalho. As restrições compatíveis são os métodos definidos em Constraints.Builder
. Para saber mais, consulte Como definir suas solicitações de trabalho.
Etapa 1: adicionar um objeto Constraints e definir uma restrição
Nesta etapa, você criará um objeto Constraints
e definirá uma restrição nele, uma restrição de tipo de rede. É mais fácil observar os registros com apenas uma restrição. Em uma etapa posterior, você adicionará outras restrições.
- Na classe
DevByteApplication
, no início do métodosetupRecurringWork()
, defina umval
do tipoConstraints
. Use o métodoConstraints.Builder()
.
val constraints = Constraints.Builder()
Para resolver o erro, importe androidx.work.Constraints
.
- Use o método
setRequiredNetworkType()
para adicionar uma restrição de tipo de rede ao objetoconstraints
. Use a enumeraçãoUNMETERED
para que a solicitação de trabalho seja executada somente quando o dispositivo estiver em uma rede ilimitada.
.setRequiredNetworkType(NetworkType.UNMETERED)
- Use o método
build()
para gerar as restrições do builder.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.build()
Agora, você precisa definir o objeto Constraints
recém-criado como a solicitação de trabalho.
- Na classe
DevByteApplication
, no métodosetupRecurringWork()
, defina o objetoConstraints
como a solicitação de trabalho periódica,repeatingRequest
. Para definir as restrições, adicione o métodosetConstraints()
acima da chamada do métodobuild()
.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(15, TimeUnit.MINUTES)
.setConstraints(constraints)
.build()
Etapa 2: executar o app e ver os registros
Nesta etapa, você executa o app e percebe que a solicitação de trabalho restrito é executada em segundo plano em intervalos.
- Desinstale o app do dispositivo ou emulador para cancelar qualquer tarefa programada anteriormente.
- Abra o painel Logcat no Android Studio. No painel Logcat, limpe os registros anteriores clicando no ícone Clear logcat
à esquerda. Filtrar em
work
. - Desative o Wi-Fi no dispositivo ou emulador para ver como as restrições funcionam. O código atual define apenas uma restrição, indicando que a solicitação precisa ser executada apenas em uma rede ilimitada. Como o Wi-Fi está desativado, o dispositivo não está conectado à rede, limitada ou ilimitada. Portanto, essa restrição não será atendida.
- Execute o app e veja o painel do Logcat. O
WorkManager
programa a tarefa em segundo plano imediatamente. Como a restrição de rede não foi atendida, a tarefa não foi executada.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled
- Ative o Wi-Fi no dispositivo ou emulador e veja o painel Logcat. Agora a tarefa em segundo plano programada será executada aproximadamente a cada 15 minutos, contanto que a restrição de rede seja atendida.
11:31:44 D/DevByteApplication: Periodic Work request for sync is scheduled 11:31:47 D/RefreshDataWorker: Work request for sync is run 11:31:47 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 11:46:45 D/RefreshDataWorker: Work request for sync is run 11:46:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:03:05 D/RefreshDataWorker: Work request for sync is run 12:03:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:16:45 D/RefreshDataWorker: Work request for sync is run 12:16:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:31:45 D/RefreshDataWorker: Work request for sync is run 12:31:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 12:47:05 D/RefreshDataWorker: Work request for sync is run 12:47:05 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...] 13:01:45 D/RefreshDataWorker: Work request for sync is run 13:01:45 I/WM-WorkerWrapper: Worker result SUCCESS for Work [...]
Etapa 3: adicionar mais restrições
Nesta etapa, você adicionará as seguintes restrições ao PeriodicWorkRequest
:
- A bateria não está fraca.
- Carregando o dispositivo.
- Dispositivo inativo, disponível apenas no nível de API 23 (Android M) e superior.
Implemente o seguinte na classe DevByteApplication
.
- Na classe
DevByteApplication
, no métodosetupRecurringWork()
, indique que a solicitação de trabalho será executada somente se a bateria não estiver acabando. Adicione a restrição antes da chamada de métodobuild()
e use o métodosetRequiresBatteryNotLow()
.
.setRequiresBatteryNotLow(true)
- Atualize a solicitação de trabalho para que ela seja executada somente quando o dispositivo estiver sendo carregado. Adicione a restrição antes da chamada de método
build()
e use o métodosetRequiresCharging()
.
.setRequiresCharging(true)
- Atualize a solicitação de trabalho para ser executada somente quando o dispositivo estiver inativo. Adicione a restrição antes da chamada de método
build()
e use o métodosetRequiresDeviceIdle()
. Essa restrição executa a solicitação de trabalho somente quando o usuário não está usando o dispositivo ativamente. Esse recurso está disponível apenas no Android 6.0 (Marshmallow) e versões posteriores. Portanto, adicione uma condição para o SDK versãoM
e mais recentes.
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
Veja a definição completa do objeto constraints
.
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()
- No método
setupRecurringWork()
, altere o intervalo de solicitação novamente para uma vez por dia.
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
Veja a implementação completa do método setupRecurringWork()
, com um registro para que você possa acompanhar quando a solicitação de trabalho periódica está programada.
private fun setupRecurringWork() {
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
.setRequiresCharging(true)
.apply {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
setRequiresDeviceIdle(true)
}
}
.build()
val repeatingRequest = PeriodicWorkRequestBuilder<RefreshDataWorker>(1, TimeUnit.DAYS)
.setConstraints(constraints)
.build()
Timber.d("Periodic Work request for sync is scheduled")
WorkManager.getInstance().enqueueUniquePeriodicWork(
RefreshDataWorker.WORK_NAME,
ExistingPeriodicWorkPolicy.KEEP,
repeatingRequest)
}
- Para remover a solicitação de trabalho programada anteriormente, desinstale o app DevBytes do dispositivo ou do emulador.
- Execute o app, e o
WorkManager
programará imediatamente a solicitação de trabalho. A solicitação de trabalho é executada uma vez por dia, quando todas as restrições são atendidas. - Essa solicitação de trabalho será executada em segundo plano enquanto o app estiver instalado, mesmo que ele não esteja em execução. Por esse motivo, você deve desinstalar o app do smartphone.
Muito bem! Você implementou e programou uma solicitação de trabalho com baixo consumo de bateria para a pré-busca diária de vídeos no app DevBytes. O WorkManager
programará e executará o trabalho, otimizando os recursos do sistema. Os usuários e as baterias ficarão muito felizes.
Projeto do Android Studio: DevBytesWorkManager.
- A API
WorkManager
facilita a programação de tarefas adiáveis e assíncronas que precisam ser executadas de maneira confiável. - A maioria dos apps reais precisa executar tarefas em segundo plano de longa duração. Para programar uma tarefa em segundo plano de maneira otimizada e eficiente, use
WorkManager
. - As principais classes na biblioteca
WorkManager
sãoWorker
,WorkRequest
eWorkManager
. - A classe
Worker
representa uma unidade de trabalho. Para implementar a tarefa em segundo plano, estenda a classeWorker
e modifique o métododoWork()
. - A classe
WorkRequest
representa uma solicitação para executar uma unidade de trabalho.WorkRequest
é a classe básica para especificar parâmetros para o trabalho programado emWorkManager
. - Há duas implementações concretas da classe
WorkRequest
:OneTimeWorkRequest
para tarefas únicas ePeriodicWorkRequest
para solicitações de trabalho periódicas. - Ao definir o
WorkRequest
, você pode especificarConstraints
indicando quando oWorker
será executado. Isso inclui saber se o dispositivo está conectado, se ele está inativo ou se o Wi-Fi está conectado. - Para adicionar restrições à
WorkRequest
, use os métodos de conjunto listados na documentação deConstraints.Builder
. Por exemplo, para indicar que oWorkRequest
não pode ser executado se a bateria do dispositivo estiver baixa, use o métodosetRequiresBatteryNotLow()
definido. - Depois de definir o
WorkRequest
, entregue a tarefa ao sistema Android. Para fazer isso, programe a tarefa usando um dos métodosenqueue
WorkManager
. - O tempo exato em que o
Worker
é executado depende das restrições usadas noWorkRequest
e das otimizações do sistema. OWorkManager
foi projetado para oferecer o melhor comportamento possível, de acordo com essas restrições.
Curso da Udacity:
- Como desenvolver apps Android com Kotlin (link em inglês)
Documentação do desenvolvedor Android:
- Como definir suas solicitações de trabalho
WorkManager
- Primeiros passos com o WorkManager
- Trabalho recorrente
- Guia para o processamento em segundo plano
Outro:
Esta seção lista as possíveis atividades para os alunos que estão trabalhando neste codelab como parte de um curso ministrado por um instrutor. Cabe ao instrutor fazer o seguinte:
- Se necessário, atribua o dever de casa.
- Informe aos alunos como enviar o dever de casa.
- Atribua nota aos trabalhos de casa.
Os professores podem usar essas sugestões o quanto quiserem, e eles devem se sentir à vontade para passar o dever de casa como achar adequado.
Se você estiver fazendo este codelab por conta própria, use essas atividades para testar seu conhecimento.
Pergunta 1
Quais são as implementações concretas da classe WorkRequest
?
▢ OneTimeWorkPeriodicRequest
▢ OneTimeWorkRequest
e PeriodicWorkRequest
▢ OneTimeWorkRequest
e RecurringWorkRequest
▢ OneTimeOffWorkRequest
e RecurringWorkRequest
Pergunta 2
Qual das seguintes classes o WorkManager
usa para programar a tarefa em segundo plano na API 23 e versões mais recentes?
▢ Apenas JobScheduler
▢ BroadcastReceiver
e AlarmManager
▢ AlarmManager
e JobScheduler
▢ Scheduler
e BroadcastReceiver
Pergunta 3
Qual API você usa para adicionar restrições a um WorkRequest
?
▢ setConstraints()
▢ addConstraints()
▢ setConstraint()
▢ addConstraintsToWorkRequest()
Vá para a próxima lição:
Para ver links de outros codelabs neste curso, consulte a página de destino dos codelabs do curso Conceitos básicos do Kotlin para Android.