onPause é um método do ciclo de vida do Android que é chamado quando uma Activity perde o foco de entrada mas permanece parcialmente visível na tela. O sistema chama onPause antes de uma nova Activity vir para o primeiro plano, ao abrir uma caixa de diálogo, ao pressionar o botão de Aplicativos Recentes ou ao receber uma chamada recebida. Este método é o último ponto garantido para salvar dados do usuário, pois após onStop e onDestroy o sistema pode encerrar o processo sem chamadas adicionais. Dentro de onPause, o desenvolvedor salva rascunhos, pausa animações, libera a câmera e escreve o estado atual da UI no SharedPreferences. Para mais detalhes sobre o ciclo de vida completo da Activity, leia o artigo Activity Lifecycle.
Principais Conclusões
onPause é o quarto método do ciclo de vida da Activity, chamado quando a tela perde o foco de entrada mas permanece parcialmente visível para o usuário. É um estado de «transição» entre o aplicativo rodando ativamente e sua ocultação. O sistema chama onPause nos seguintes cenários: abertura de outra Activity (uma nova tela cobre parcialmente a atual), aparecimento de uma caixa de diálogo (Dialog, PopupWindow, Snackbar não acionam onPause, mas DialogFragment sim), pressionar o botão de Aplicativos Recentes, chamada recebida, pressionar o botão Power para bloquear a tela.
A principal tarefa do onPause é preparar o aplicativo para a possibilidade de ser ocultado ou destruído. Este é o último ponto no ciclo de vida onde o desenvolvedor pode ter certeza de que seu código será executado antes que o sistema prossiga com a transição para outro componente. Após onPause, o sistema chama onStop (se a Activity for completamente ocultada), após o qual o processo pode ser encerrado a qualquer momento sem notificação adicional.
De acordo com a documentação do Android Developers (2025), onPause deve ser o mais leve e rápido possível. Enquanto onPause não retornar o controle, o sistema não pode iniciar a próxima Activity — isso significa que o usuário vê um atraso na transição de tela. O Google recomenda concluir onPause em menos de 100 milissegundos, e todas as operações longas (salvar em banco de dados, gravar em disco) devem ser realizadas de forma assíncrona através de corrotinas ou apply().
Em uma Activity, o método onPause é chamado toda vez que a tela deixa de estar ativa mas pode continuar sendo exibida parcialmente. Um exemplo típico: o usuário abre o aplicativo Mapas, toca em Compartilhar Localização, e um diálogo do sistema de seleção de aplicativo aparece sobre o Mapas. A Activity do Mapas recebe onPause mas permanece visível abaixo do diálogo. Quando o diálogo é fechado, o Mapas recebe onResume sem que onStart seja chamado (a tela não foi completamente ocultada).
class NoteEditorActivity : AppCompatActivity() {
private var binding: ActivityNoteEditorBinding? = null
private val prefs by lazy {
getSharedPreferences("note_drafts", Context.MODE_PRIVATE)
}
override fun onPause() {
super.onPause()
// Salvar rascunho da nota — assincronamente
prefs.edit()
.putString("draft_title", binding?.titleInput?.text.toString())
.putString("draft_body", binding?.bodyInput?.text.toString())
.putLong("draft_timestamp", System.currentTimeMillis())
.apply()
// Pausar vídeo
binding?.videoPlayer?.pause()
// Liberar recursos exclusivos
releaseCamera()
releaseAudioFocus()
}
override fun onResume() {
super.onResume()
// Restaurar rascunho
binding?.titleInput?.setText(prefs.getString("draft_title", ""))
binding?.bodyInput?.setText(prefs.getString("draft_body", ""))
acquireCamera()
acquireAudioFocus()
}
}
O exemplo NoteEditorActivity demonstra o manuseio correto do onPause: salvar um rascunho no SharedPreferences através de apply(), pausar um arquivo de vídeo, liberar a câmera e o foco de áudio. Cada chamada é leve e rápida, sem bloquear a thread da UI tempo suficiente para causar ANR. Observe a ordem: super.onPause() é chamado na primeira linha — isso garante que a lógica do sistema execute mesmo se ocorrer uma exceção no código do usuário.
onPause é o último ponto onde o desenvolvedor pode salvar dados do usuário de forma confiável antes do aplicativo ser ocultado ou morto pelo sistema. Após onStop, o sistema pode encerrar o processo se a memória estiver baixa, sem chamar onDestroy. O método onSaveInstanceState() é chamado após onPause, mas seu Bundle não se destina a armazenamento de longo prazo — ele vive apenas até o próximo onCreate.
SharedPreferences com apply() assíncrono é a maneira ótima de salvar pequenas quantidades de dados em onPause. Ao contrário de commit(), que grava dados de forma síncrona no disco e retorna um booleano, apply() salva imediatamente os dados na memória e agenda uma gravação assíncrona no disco. Isso leva menos de 1 milissegundo na thread da UI contra 10–100 milissegundos de commit().
override fun onPause() {
super.onPause()
// ❌ Ruim: gravação síncrona bloqueia a thread
// prefs.edit().putInt("score", score).commit()
// ✅ Bom: gravação assíncrona
prefs.edit().putInt("score", score).apply()
// Para objetos complexos — armazenamento em cache no ViewModel
viewModel.saveState()
}
Para dados estruturados (SQLite via Room) em onPause, use corrotinas com lifecycleScope. ViewModelScope cancela automaticamente a corrotina quando o ViewModel é destruído, prevenindo gravações em um banco de dados fechado. A gravação via Room com corrotinas leva 5–15 milissegundos e não bloqueia a thread da UI.
// No ViewModel:
fun saveDraft(title: String, body: String) {
viewModelScope.launch(Dispatchers.IO) {
noteDao.insert(NoteDraft(title = title, body = body))
}
}
// Em Activity.onPause:
viewModel.saveDraft(
binding?.titleInput?.text.toString(),
binding?.bodyInput?.text.toString()
)
onPause no Fragment é chamado quando o Fragment deixa de estar ativo mas pode permanecer visível. Isso ocorre quando: um Fragment é substituído por outro Fragment via FragmentTransaction; um Fragment deixa de ser a página atual em um ViewPager; a Activity que contém o Fragment recebe onPause. A interação entre onPause da Activity e onPause do Fragment é estritamente hierárquica: primeiro a Activity recebe onPause, depois todos os seus Fragments.
class MapFragment : Fragment() {
private var mapController: MapController? = null
override fun onPause() {
super.onPause()
mapController?.stopFollowMode()
binding?.mapContainer?.alpha = 0.7f
}
override fun onResume() {
super.onResume()
binding?.mapContainer?.alpha = 1.0f
if (isVisible) {
mapController?.startFollowMode()
}
}
}
Especificidades de trabalhar com mapas em onPause: Google Maps e Yandex Maps consomem recursos significativos de GPU no modo de acompanhamento ativo. Ao perder o foco, faz sentido desabilitar a animação do mapa e reduzir a frequência de atualização dos marcadores, e ao recuperar o foco, restaurar a funcionalidade completa. Isso melhora o desempenho e reduz o consumo de energia ao alternar entre telas.
Uma das confusões mais comuns entre desenvolvedores Android iniciantes é não entender a diferença entre onPause e onStop. Vamos examinar cada cenário e determinar o método correto.
| Cenário | onPause | onStop |
|---|---|---|
| Abrir uma caixa de diálogo | Chamado | Não chamado |
| Abrir uma nova Activity (não transparente) | Chamado | Chamado |
| Pressionar o botão Início | Chamado | Chamado |
| Bloqueio de tela | Chamado | Chamado |
| Chamada recebida | Chamado | Chamado |
| Activity transparente sobreposta | Chamado | Não chamado |
| Split Screen (metade da tela) | Chamado | Não chamado |
| PiP (Picture-in-Picture) | Chamado | Não chamado |
A regra principal: onPause é chamado em qualquer perda de foco, onStop é chamado apenas quando a visibilidade é completamente perdida. Se a Activity permanece visível (mesmo que parcialmente), onStop não é chamado. Isso é criticamente importante para os modos Split Screen, PiP e Activity transparente — aqui onPause/onResume funcionam, mas onStart/onStop não.
onPause é o método do ciclo de vida mais crítico em termos de tempo, pois bloqueia a renderização da próxima Activity. O sistema espera a conclusão do onPause da Activity atual antes de mostrar a nova. Se onPause levar mais de 100 milissegundos, o usuário nota um atraso na transição; se levar mais de 5 segundos, o sistema exibe um ANR.
O Guia de Desempenho Android do Google (2025) oferece as seguintes recomendações para onPause: não realize requisições de rede — elas devem ser canceladas ou movidas para o WorkManager; não grave arquivos grandes em disco — use BufferedWriter em uma thread em segundo plano; não execute consultas SQL complexas — operações Room devem ser assíncronas via corrotinas; evite criar novos objetos — a coleta de lixo em onPause agrava o atraso; use apply() em vez de commit() para SharedPreferences.
override fun onPause() {
super.onPause()
// ❌ Ruim: requisição HTTP bloqueia a UI
// val response = api.syncSave(data).execute()
// ❌ Ruim: gravação síncrona em arquivo
// FileOutputStream(file).write(data)
// ✅ Bom: salvamento assíncrono
lifecycleScope.launch {
withContext(Dispatchers.IO) {
api.saveData(data)
fileDao.write(data)
}
}
// ✅ Bom: gravação leve no SharedPreferences
prefs.edit().putString("key", value).apply()
}
A criação de perfil do onPause via Android Studio Profiler (traço de CPU) mostra o tempo exato de execução. Se onPause levar mais de 100 ms, o Profiler destaca o método em amarelo, e mais de 500 ms em vermelho. Em projetos comerciais na IT Sectr, usamos testes Macrobenchmark que verificam automaticamente o tempo de transição entre Activities e sinalizam regressões de desempenho no pipeline de CI.
Até desenvolvedores experientes cometem erros em onPause. Vamos examinar cinco problemas típicos e suas soluções.
Chamar Room DAO com uma consulta síncrona (.executeAsObservable() sem corrotinas) em onPause bloqueia a thread da UI por 10–50 ms. Se GC ou contenção de gravação ocorrer ao mesmo tempo, o atraso pode chegar a 200–500 ms. Solução: use corrotinas com Dispatchers.IO ou apply() para SharedPreferences.
onPause não é lugar para registrar listeners. Se você registrar um BroadcastReceiver em onPause, ele permanecerá ativo quando a Activity não estiver mais visível. O registro deve ser feito apenas em onStart/onResume, e em onPause/onStop — apenas cancelamento de registro. A exceção são APIs baseadas em Intent que exigem registro antes da chamada.
Se uma exceção não tratada ocorrer em onPause, o sistema não chama onStop e onDestroy. A Activity trava em um estado indefinido, e onResume ao retornar pode não restaurar corretamente os recursos liberados. Solução: envolva operações críticas em try/catch com registro via Log.e().
Não há necessidade de salvar em onPause dados que podem ser facilmente restaurados. Por exemplo, resultados de requisições a API são armazenados em cache no Room ou DataStore no momento da obtenção, não em onPause. Salve apenas o que o usuário inseriu manualmente e não pode ser restaurado automaticamente — texto em campos, itens selecionados, posição de rolagem.
super.onPause() deve ser chamado, mas ao contrário de onCreate, omiti-lo não causa uma falha imediata. O sistema «perdoa» a falta de super em onPause, mas a máquina de estados interna entra em um estado incorreto. A próxima chamada onResume pode não restaurar o foco de entrada, deixando a Activity “congelada.” Sempre chame super.onPause() o mais cedo possível.
Perguntas Frequentes
Chamar finish() em onPause encerrará a Activity imediatamente após retornar do método. Este é um cenário válido se a tela precisar ser fechada ao perder o foco (por exemplo, uma tela de autorização ao minimizar o aplicativo). No entanto, finish() aciona o ciclo completo de encerramento: onStop onDestroy, o que adiciona um atraso à transição. Use finish() em onPause apenas quando realmente necessário.
onPause é para salvar dados que devem sobreviver ao encerramento do processo (rascunhos no SharedPreferences/Room). onSaveInstanceState é para salvar estado temporário da UI que só é necessário até o próximo onCreate (posição de rolagem, aba selecionada). O Bundle do onSaveInstanceState não é preservado quando o aplicativo é completamente encerrado — ele existe apenas na memória. Os dados do onPause são salvos em disco e sobrevivem a uma reinicialização.
Não é recomendado. Abrir um diálogo ou popup em onPause causa WindowLeakException se a Activity já foi finalizada. Se precisar mostrar uma notificação ao perder o foco, use NotificationManager (notificações do sistema) — é seguro e esperado pelo usuário. Para ações adiadas, use AlarmManager ou WorkManager.
onPause é garantido de ser chamado antes da Activity deixar de estar ativa. onStop pode não ser chamado se o sistema matar o processo para liberar memória — neste caso, onDestroy também não é chamado. onPause é o único método após onResume que é sempre chamado, independentemente do motivo da perda de foco. Portanto, todos os dados críticos são salvos precisamente em onPause.
Para testar onPause, use Robolectric ou FragmentScenario do AndroidX Test. FragmentScenario.create() moveToState(State.STARTED) moveToState(State.RESUMED) moveToState(State.STARTED) chama onPause sequencialmente. Em seguida, verifique se os dados foram salvos no SharedPreferences ou se a câmera foi liberada através de um objeto mock. Robolectric 4.12+ suporta emulação de onPause/onResume sem um dispositivo físico.
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