lifecycleScope é um CoroutineScope integrado da biblioteca androidx.lifecycle, vinculado ao ciclo de vida de uma Activity, Fragment ou qualquer LifecycleOwner, e cancela automaticamente as corrotinas quando o componente é destruído. De acordo com Google Android Developers, 2025, o lifecycleScope permite executar corrotinas com segurança na camada de UI sem o risco de executar código após a destruição da Activity ou Fragment. O escopo é cancelado automaticamente quando o LifecycleOwner transiciona para o estado DESTROYED.
Principais conclusões
lifecycleScope é uma propriedade de extensão na interface LifecycleOwner (Activity, Fragment, Service) que fornece um CoroutineScope pronto, vinculado ao ciclo de vida completo do componente. Quando o LifecycleOwner atinge o estado DESTROYED, o lifecycleScope cancela automaticamente todas as corrotinas ativas.
// In Fragment or Activity
lifecycleScope.launch {
delay(1000)
showSnackbar("Olá!")
}
Ao contrário do viewModelScope, o lifecycleScope é cancelado toda vez que o LifecycleOwner é destruído — incluindo a rotação da tela. Isso o torna ideal para operações que devem viver apenas enquanto uma tela específica estiver visível.
O lifecycleScope está disponível em qualquer lugar onde houver um LifecycleOwner:
O mecanismo de cancelamento automático do lifecycleScope é baseado na assinatura de eventos do Lifecycle. Quando o Lifecycle cai abaixo de CREATED para DESTROYED, o escopo é cancelado.
| Estado | Descrição | Escopo ativo |
|---|---|---|
| CREATED | LifecycleOwner criado, onCreate executado | Sim |
| STARTED | LifecycleOwner visível (onStart) | Sim |
| RESUMED | LifecycleOwner em primeiro plano (onResume) | Sim |
| DESTROYED | LifecycleOwner destruído (onDestroy) | Não (escopo cancelado) |
O lifecycleScope é criado como CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) e armazenado dentro do Lifecycle. Quando o Lifecycle transiciona para o estado DESTROYED, scope.cancel() é chamado. O mecanismo é implementado via LifecycleEventObserver, que assina os eventos do ciclo de vida no primeiro acesso ao escopo.
Quando a tela é rotacionada, a Activity é destruída (onDestroy) e recriada. O lifecycleScope é cancelado junto com a Activity antiga, e uma nova instância do escopo é criada para a nova Activity. Esta é uma diferença fundamental do viewModelScope, que sobrevive à rotação.
A biblioteca lifecycle fornece várias maneiras de iniciar corrotinas através do lifecycleScope. Vamos ver a evolução da API dos métodos obsoletos para os modernos.
A forma mais simples é lifecycleScope.launch { ... }. A corrotina inicia imediatamente e é cancelada em DESTROYED. No entanto, ela pode executar código mesmo quando a UI não está visível (por exemplo, em segundo plano após onStop). Isso nem sempre é desejável.
Esses métodos pausavam a execução da corrotina quando o Lifecycle caía abaixo do estado especificado e a retomavam ao retornar. No entanto, foram marcados como @Deprecated no lifecycle-runtime-ktx 2.6.0 porque:
repeatOnLifecycle é a maneira recomendada pelo Google para iniciar corrotinas sincronizadas com o ciclo de vida. Ele cancela e reinicia a corrotina toda vez que o Lifecycle atinge o estado especificado.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.uiState.collect { state ->
updateUI(state)
}
}
}
A corrotina passada para repeatOnLifecycle inicia quando o Lifecycle atinge STARTED e é cancelada quando cai abaixo de STARTED. Ao retornar a STARTED, a corrotina reinicia do zero. Isso é seguro e eficiente — nenhuma corrotina fica suspensa.
Para coletar dados do Flow com ciência do ciclo de vida, existe o operador flowWithLifecycle. Ele para e retoma automaticamente a coleta quando o estado do Lifecycle muda:
viewModel.uiState
.flowWithLifecycle(lifecycle, Lifecycle.State.STARTED)
.onEach { state -> updateUI(state) }
.launchIn(lifecycleScope)
O operador flowWithLifecycle é a maneira mais concisa de assinar um Flow com segurança na camada de UI.
Vamos ver três cenários reais de uso do lifecycleScope em uma aplicação Android com Kotlin.
class MapFragment : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
locationProvider.observeLocation().collect { loc ->
updateMapMarker(loc)
}
}
}
}
}
A corrotina inicia quando o fragmento se torna visível (STARTED) e é cancelada quando sai da tela (STOPPED). Se o usuário mudar para outro aplicativo, as atualizações de localização não consomem bateria.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.RESUMED) {
animateFadeIn(titleView)
delay(200)
animateSlideUp(contentView)
}
}
A animação é executada apenas quando o fragmento está em primeiro plano (RESUMED). Se o usuário minimizar o aplicativo durante a animação, a corrotina é cancelada e, ao retornar, a animação reinicia.
lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
while (isActive) {
syncData()
delay(30_000L)
}
}
}
Os dados são sincronizados a cada 30 segundos, mas apenas quando a tela está visível. isActive verifica se a corrotina foi cancelada, fornecendo uma saída segura do loop ao sair da tela.
Ambos os escopos estão vinculados ao ciclo de vida, mas a aspectos diferentes dele. Entender a diferença é crítico para uma arquitetura adequada de aplicativos Android.
viewModelScope está vinculado ao ViewModel, que sobrevive à rotação da tela. lifecycleScope está vinculado ao LifecycleOwner (Activity/Fragment), que é destruído e recriado na rotação. Isso determina seus cenários de uso.
Na prática, é comum uma combinação de ambos os escopos: viewModelScope carrega dados e gerencia o estado, enquanto lifecycleScope assina o Flow do ViewModel com ciência do ciclo de vida. Essa separação de responsabilidades é considerada boa prática no desenvolvimento moderno de Android.
Vamos ver quatro dos erros mais comuns que os desenvolvedores cometem ao usar o lifecycleScope.
Se você iniciar o carregamento de dados em lifecycleScope.launch, a corrotina será cancelada na rotação da tela e os dados terão que ser recarregados. Use viewModelScope para operações de longa duração. lifecycleScope é apenas para tarefas vinculadas à UI.
Chamar diretamente viewModel.someFlow.collect { ... } dentro de lifecycleScope.launch continua coletando dados mesmo quando a tela não está visível. Isso pode levar a atualizações de UI em segundo plano e sobrecarga desnecessária. Sempre use repeatOnLifecycle ou flowWithLifecycle.
Embora o lifecycleScope seja cancelado em DESTROYED, o código após um ponto de suspensão pode não ser executado em caso de cancelamento repentino. Não confie na execução de pós-código após uma chamada suspend, a menos que use NonCancellable.
launchWhenStarted e seus equivalentes não cancelam a corrotina, apenas a pausam. Se a tela alternar entre primeiro e segundo plano várias vezes, a corrotina acumula chamadas adiadas. Migre para repeatOnLifecycle — esta é a única maneira correta de sincronizar com o Lifecycle.
Perguntas frequentes
lifecycleScope é cancelado automaticamente quando o LifecycleOwner é destruído. GlobalScope vive durante toda a duração do aplicativo. Uma corrotina no lifecycleScope não pode atualizar a UI após a destruição do componente, enquanto no GlobalScope pode, causando falhas. Sempre use lifecycleScope na camada de UI.
Não, ViewModel não é um LifecycleOwner, portanto o lifecycleScope não está disponível nele. ViewModel usa viewModelScope. Se o código precisar ser executado em ambos os contextos, extraia a lógica para um use case ou repository com funções suspend.
Cada chamada a repeatOnLifecycle cria uma nova corrotina que executa o bloco quando o estado especificado do Lifecycle é atingido. Se repeatOnLifecycle for chamado duas vezes para o mesmo estado, ambos os blocos serão executados de forma independente. Normalmente, uma chamada em onViewCreated é suficiente.
Não é possível alterar diretamente o dispatcher do lifecycleScope — ele usa Dispatchers.Main.immediate. Dentro do bloco da corrotina, você pode mudar para outro dispatcher via withContext. Para testes, use TestDispatcher com LifecycleOwner.
O lifecycleScope é cancelado quando o LifecycleOwner transiciona para o estado DESTROYED (após onDestroy). Chamadas simples de lifecycleScope.launch não são canceladas em onPause ou onStop. Para pausar ao ir para segundo plano, use repeatOnLifecycle(STARTED) ou repeatOnLifecycle(RESUMED).
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também