onPause: o que é, salvar estado de Activity no Android

Autor: IT Sectr Publicado: 2026-03-04 Tempo de leitura: 10 min

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 — Activity perde o foco mas permanece visível; último ponto garantido para salvar dados
  • Salvar Estado — em onPause são salvos dados críticos do usuário: rascunhos, texto em formulários, progresso
  • Liberar Recursos — câmera, microfone, player de vídeo são liberados em onPause para transferência a outro aplicativo
  • Limite de Tempo — onPause deve ser concluído em 100 ms; exceder isso causa ANR e atrasa a transição
  • SharedPreferences.apply() — escrita assíncrona em onPause; commit() bloqueia a thread e pode causar ANR
  • onPause vs onStop — onPause com visibilidade parcial (diálogo), onStop com ocultação total (outra Activity)
  • onSaveInstanceState — chamado após onPause para salvar estado temporário em um Bundle

O que é onPause no Android

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().

onPause na Activity

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).

kotlin
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.

Salvar Estado em onPause

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()

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().

kotlin
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()
}

Room e Corrotinas

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.

kotlin
// 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

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.

kotlin
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.

onPause vs onStop: Diferença e Cenários

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árioonPauseonStop
Abrir uma caixa de diálogoChamadoNão chamado
Abrir uma nova Activity (não transparente)ChamadoChamado
Pressionar o botão InícioChamadoChamado
Bloqueio de telaChamadoChamado
Chamada recebidaChamadoChamado
Activity transparente sobrepostaChamadoNão chamado
Split Screen (metade da tela)ChamadoNão chamado
PiP (Picture-in-Picture)ChamadoNã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.

Tempo e Desempenho do onPause

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.

Recomendações de Desempenho

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.

kotlin
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.

Erros Comuns em onPause

Até desenvolvedores experientes cometem erros em onPause. Vamos examinar cinco problemas típicos e suas soluções.

Gravação Síncrona em Banco de Dados

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.

Registrar Novos Listeners

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.

Ignorar Exceções

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().

Salvar Dados Redundantes

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.

Esqueceu super.onPause()

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

O que acontece se chamar finish() em onPause?

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.

Como onPause difere de onSaveInstanceState?

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.

Posso abrir um diálogo em onPause?

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.

Por que onPause é um ponto de salvamento garantido, mas onStop não?

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.

Como testar onPause em testes unitários?

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

  • onPause — Activity perde o foco de entrada mas permanece parcialmente visível; último ponto garantido para salvar dados
  • Salvamento — SharedPreferences.apply() ou Room via corrotinas; commit() e operações síncronas são proibidos
  • Liberação de Recursos — câmera, foco de áudio, player de vídeo são liberados em onPause para transferência a outro aplicativo
  • Limite de 100 ms — onPause bloqueia a renderização da próxima Activity; exceder o limite causa ANR
  • onPause vs onStop — onPause na perda de foco (visibilidade preservada), onStop na ocultação total
  • Fragment.onPause — chamada hierárquica após Activity.onPause; especificidades para mapas e ViewPager
  • Erros Comuns — gravação síncrona, registro de listeners, ignorar try/catch, salvamento redundante
  • super.onPause() — chame o mais cedo possível; omitir não causa falha mas quebra a máquina de estados

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.

Discutir o projeto

Leia também