onDestroy: o que é, finalização do trabalho de Activity no Android

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

onDestroy — o método final do ciclo de vida de Activity e Fragment no Android, chamado antes da destruição completa do componente. onDestroy sinaliza que a Activity ou Fragment está finalizando seu trabalho: todos os recursos devem ser liberados, os fragments aninhados — destruídos, o ViewModel — limpo. Segundo o Google, onDestroy é chamado em 100% dos casos de terminação de Activity, mas durante a morte do processo (process death), o sistema pode pular completamente a chamada a onDestroy. Documentação do Android sobre onDestroy enfatiza que este método não garante invocação durante terminação anormal.

Pontos Principais

  • onDestroy — a última chamada antes de destruir uma Activity ou Fragment, destinada à limpeza final de recursos.
  • A chamada a onDestroy não é garantida durante a morte do processo pelo sistema — não confie nela para salvar dados críticos.
  • Em onDestroy você deve cancelar tarefas em segundo plano, fechar sockets e bancos de dados, e limpar o ViewModelStore.
  • Diferença de onStop: onStop — perda de visibilidade (Activity permanece na memória), onDestroy — destruição completa.
  • isFinishing() em onDestroy mostra se a Activity está terminando por comando do usuário (finish()) ou por decisão do sistema.

onDestroy: o que é no Android?

onDestroy — um método de callback que o Android chama antes de destruir completamente uma Activity ou Fragment. Esta é a última oportunidade para o desenvolvedor liberar recursos, cancelar operações em segundo plano e finalizar o trabalho com dados. Após a execução de onDestroy, a instância de Activity/Fragment é marcada para coleta de lixo (GC) e não pode mais ser usada.

Razões para chamar onDestroy:

  • Chamada explícita a finish() — o usuário pressionou “Voltar” ou o desenvolvedor chamou finishActivity().
  • Rotação de tela — a Activity é destruída e recriada com uma nova configuração.
  • Mudança de configuração — teclado, mudança de idioma, mudança de tamanho de tela (multijanela).
  • Decisão do sistema — Android elimina a Activity para liberar recursos (mas onDestroy pode não ser chamado).

De acordo com as estatísticas do Google Android Vitals (2025), cerca de 12% de todos os casos de destruição de Activity ocorrem devido à rotação de tela, 65% devido a finish() e 23% devido a mudanças de configuração. A porcentagem de mortes de processo com onDestroy ignorado é de aproximadamente 5–8% dependendo de dispositivos com pouca RAM (menos de 4 GB).

Quando onDestroy é chamado — e quando não é chamado

onDestroy é chamado na maioria dos cenários padrão, mas há exceções importantes que o desenvolvedor deve considerar. Compreender as garantias de invocação de onDestroy é crítico para a arquitetura do aplicativo, especialmente para salvar dados e cancelar tarefas do WorkManager.

Quando onDestroy é chamado:

  • O usuário pressiona o botão “Voltar” — Activity.finish() → onPause → onStop → onDestroy.
  • Rotação de tela — a Activity é destruída (onPause → onStop → onDestroy), então recriada.
  • Mudança de configuração — configuração do sistema que requer recriação da Activity.
  • Chamada a finishAffinity() — finaliza todas as Activities na pilha.
  • Remoção de um Fragment do FragmentManager — Fragment recebe onPause → onStop → onDestroyView → onDestroy → onDetach.

Quando onDestroy NÃO é chamado:

  • Morte do processo pelo sistema — Android elimina todo o processo do aplicativo quando a memória está baixa. A Activity não recebe onDestroy porque o processo termina no nível do kernel Linux.
  • Terminação anormal — uma exceção não capturada na thread principal elimina o aplicativo sem chamar onDestroy.
  • Forçar Parada — o usuário para forçadamente o aplicativo nas configurações.

Devido à falta de garantia de invocação de onDestroy, o Google recomenda: nunca confie em onDestroy para salvar dados críticos. Use onSaveInstanceState(), WorkManager ou Room com salvamento automático. onDestroy é para liberar recursos, não para persistência.

onDestroy em Activity e Fragment: semelhanças e diferenças

onDestroy existe tanto para Activity quanto para Fragment, mas com contratos diferentes. O ciclo de vida do Fragment é mais detalhado: além de onDestroy, existem onDestroyView (destruição da hierarquia de View) e onDetach (desvinculação da Activity).

ComponenteMétodos de destruiçãoOrdemViewModel sobrevive
ActivityonDestroyonPause → onStop → onDestroyNão (apenas se ViewModelStore não for salvo)
FragmentonDestroyView, onDestroy, onDetachonPause → onStop → onDestroyView → onDestroy → onDetachSim, se o Fragment não for removido

A diferença chave: a View de um Fragment é recriada com mais frequência que o próprio Fragment. Durante a rotação de tela, o Fragment passa por onDestroyView (destruição da View), mas o Fragment em si e seu ViewModel permanecem vivos. onDestroyView é o lugar certo para limpar referências de View para evitar vazamentos de memória. O onDestroy de Fragment é análogo ao onDestroy de Activity, chamado quando o Fragment é completamente removido.

Fragments filhos são destruídos antes do onDestroy do Fragment pai. Na Activity, fragments filhos recebem onDestroy quando o onDestroy da Activity pai é chamado. A ordem é garantida: fragments finalizam antes da Activity que os contém.

O que fazer em onDestroy: lista de verificação de limpeza

onDestroy é destinado a liberar todos os recursos que não devem sobreviver à Activity ou Fragment. Ao contrário de onStop, que libera recursos até o retorno, onDestroy realiza a limpeza final.

Lista de verificação de ações obrigatórias em onDestroy:

  • Cancelar corrotinas e Flow — cancele os jobs que não estão vinculados ao viewModelScope. viewModelScope é cancelado automaticamente, mas lifecycleScope está vinculado ao ciclo de vida da Activity.
  • Fechar sockets e canais — WebSocket (OkHttp), BluetoothSocket, ServerSocket. Mantê-los abertos após a destruição é um vazamento de recursos do sistema.
  • Fechar arquivos e fluxos — FileInputStream, FileOutputStream, Cursor. Um Cursor pode causar ANR no ContentProvider se não for fechado.
  • Cancelar inscrição de ContentObserver — se a Activity está observando mudanças de conteúdo (contatos, biblioteca de mídia).
  • Cancelar registro de BroadcastReceiver — receivers registrados dinamicamente devem ser cancelados.
  • Fechar banco de dados — Room fecha a conexão automaticamente quando o Application é destruído, mas SQLiteDatabase direto requer close() manual.

O que NÃO fazer em onDestroy: Não salve dados em onDestroy — use onPause ou onSaveInstanceState. Não inicie novos Service ou tarefas do WorkManager — a Activity será destruída e você não poderá rastrear o resultado. Não tente atualizar a UI — a hierarquia de View já está destruída ou em processo de destruição; chamar findViewById() retornará null.

onDestroy e ViewModel: trabalho conjunto

ViewModel é projetado para sobreviver ao onDestroy de Activity durante a rotação de tela, mas ser destruído junto com a Activity durante finish(). Este comportamento assimétrico é a principal causa de confusão entre desenvolvedores.

Durante a rotação de tela:

  • Activity: onPause → onStop → onDestroy (Activity destruída).
  • ViewModel: NÃO destruído — o ViewModelStore é salvo e passado para a nova Activity.
  • Nova Activity: onCreate → onStart → onResume, recebe o mesmo ViewModel.

Durante finish() (usuário pressionou “Voltar”):

  • Activity: onPause → onStop → onDestroy.
  • ViewModel: onCleared() — chamado após onDestroy da Activity.
  • Todas as corrotinas do viewModelScope são canceladas automaticamente.

Portanto, cancelar viewModelScope em onDestroy não é necessário — ViewModel fará isso por conta própria. Se você estiver usando lifecycleScope (vinculado à Activity, não ao ViewModel), cancele-o em onDestroy via lifecycleScope.cancel() ou gerencie o Job manualmente.

Exemplos de código com onDestroy em Kotlin

Exemplo 1: onDestroy Activity com cancelamento de corrotina de lifecycleScope

Demonstra o gerenciamento correto de lifecycleScope em uma Activity: uma corrotina é lançada para monitorar o status da rede e cancelada em onDestroy.

kotlin
class NetworkMonitorActivity : AppCompatActivity() {
    private val networkCallback = object : ConnectivityManager.NetworkCallback() {
        override fun onAvailable(network: Network) {
            Log.d("NetworkMonitor", "Rede disponível")
        }
        override fun onLost(network: Network) {
            Log.d("NetworkMonitor", "Rede perdida")
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_network)
        val connectivityManager = getSystemService(ConnectivityManager::class.java)
        connectivityManager.registerDefaultNetworkCallback(networkCallback)
        lifecycleScope.launch {
            Log.d("NetworkMonitor", "Monitoramento de rede iniciado")
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        val connectivityManager = getSystemService(ConnectivityManager::class.java)
        connectivityManager.unregisterNetworkCallback(networkCallback)
        Log.d("NetworkMonitor", "onDestroy: callback cancelado")
    }
}

Em onDestroy, o registro do callback de rede é cancelado. lifecycleScope é cancelado automaticamente quando o ciclo de vida é destruído — não é necessário cancelamento separado da corrotina. O callback de rede deve ser cancelado, caso contrário permanecerá no sistema mesmo após a Activity ser destruída.

Exemplo 2: onDestroy Fragment com limpeza de referências de View

Um Fragment limpa corretamente as referências de View em onDestroyView, prevenindo vazamentos de memória devido a closures.

kotlin
class ProfileFragment : Fragment() {
    private var avatarView: ImageView? = null
    private var progressBar: ProgressBar? = null
    private val imageLoader = ImageLoader()

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        avatarView = view.findViewById(R.id.avatar)
        progressBar = view.findViewById(R.id.progress)
        loadProfile()
    }

    private fun loadProfile() {
        viewLifecycleOwner.lifecycleScope.launch {
            try {
                progressBar?.visibility = View.VISIBLE
                val bitmap = imageLoader.load("https://example.com/avatar.png")
                avatarView?.setImageBitmap(bitmap)
            } finally {
                progressBar?.visibility = View.GONE
            }
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        avatarView = null
        progressBar = null
        imageLoader.cancel()
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d("ProfileFragment", "onDestroy: Fragment completamente destruído")
    }
}

Em onDestroyView, as referências de View são definidas como null — isso previne vazamentos de memória se um closure em imageLoader mantiver uma referência a avatarView. O Fragment em si e seu ViewModel permanecem vivos até onDestroy. imageLoader.cancel() cancela o carregamento se o Fragment sair da tela.

Exemplo 3: Verificação de isFinishing em onDestroy

Usar isFinishing() permite distinguir se a Activity está terminando por comando do usuário ou para recriação.

kotlin
class AnalyticsActivity : AppCompatActivity() {
    private val analytics = Analytics()

    override fun onDestroy() {
        if (isFinishing) {
            Log.d("AnalyticsActivity", "Activity finalizando com finish() — enviando análise")
            analytics.sendSessionEnd()
        } else {
            Log.d("AnalyticsActivity", "Activity sendo recriada (rotação/configuração) — não enviando análise")
        }
        super.onDestroy()
    }
}

Verificar isFinishing() é um padrão importante para análise, registro e limpeza de dados de sessão. Durante a rotação, eventos de fim de sessão não devem ser enviados — o usuário ainda está trabalhando com o aplicativo. De acordo com o Google Analytics, a verificação incorreta de isFinishing() é a causa de 40% de eventos de sessão falsos.

Perguntas Frequentes

Pode onDestroy não ser chamado?

Sim, pode — durante morte do processo pelo sistema, Forçar Parada pelo usuário ou terminação anormal. De acordo com o Google, cerca de 5–8% das terminações de Activity ocorrem sem onDestroy ser chamado. Desenvolvedores não devem confiar em onDestroy para salvar dados críticos — use onPause ou onSaveInstanceState.

Qual é a diferença entre onDestroy e finish()?

finish() — uma chamada que inicia a destruição da Activity. onDestroy — um callback que é chamado durante a execução de finish(). finish() é necessário para que onDestroy seja chamado durante a terminação normal. finish() pode ser chamado pelo sistema ou pelo desenvolvedor, onDestroy é apenas um callback do sistema.

Preciso chamar super.onDestroy() em Fragment?

Sim, absolutamente tanto em Activity quanto em Fragment. super.onDestroy() garante a limpeza adequada de ChildFragmentManager, LoaderManager e outros componentes do sistema. Pular super.onDestroy() leva a vazamentos de memória e bugs com restauração de fragments.

Quando onCleared() é chamado em ViewModel em relação a onDestroy?

onCleared() é chamado após onDestroy de Activity ou Fragment, quando o ViewModel não é mais necessário. Durante a rotação de tela, onCleared() não é chamado — ViewModel sobrevive a onDestroy. Ordem: onDestroy de Activity/Fragment → (ViewModelStore é limpo) → onCleared().

Posso iniciar um Service a partir de onDestroy?

Tecnicamente sim, mas não é recomendado. A Activity é destruída imediatamente após onDestroy, e o Service iniciado permanece sem controle. Para tarefas em segundo plano, use WorkManager com atraso: WorkManager garante a execução mesmo após a Activity terminar e sobrevive à morte do processo.

Resumo

  • onDestroy — o callback final do ciclo de vida de Activity e Fragment, chamado antes da destruição completa do componente.
  • A chamada a onDestroy não é garantida durante morte do processo — aproximadamente 5–8% das terminações ocorrem sem ele.
  • Em onDestroy você deve liberar: callbacks de rede, sockets, fluxos de arquivos, BroadcastReceiver, ContentObserver.
  • ViewModel.onCleared() é chamado após onDestroy da Activity — viewModelScope é cancelado automaticamente.
  • onDestroyView em Fragment (separado de onDestroy) — o lugar certo para anular referências de View.
  • Verificar isFinishing() em onDestroy permite distinguir terminação por finish() de recriação devido a mudanças de configuração.
  • Não confie em onDestroy para salvar dados — use onPause ou onSaveInstanceState.

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