Not Running — o que é, o estado inicial do ciclo de vida

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

Not Running — o estado inicial do ciclo de vida de um aplicativo móvel quando ainda não foi iniciado ou já foi encerrado. Saiba como o iOS e o Android gerenciam esse estado, quais eventos levam à transição do Not Running e como lidar corretamente com a inicialização e o encerramento do aplicativo em Swift e Kotlin.

Pontos principais

  • Not Running — o aplicativo não está carregado na memória e não está executando código; é o ponto de entrada e saída do ciclo de vida
  • Inicialização — a transição do Not Running ocorre ao tocar no ícone do aplicativo, via deep link ou notificação push
  • Encerramento — o usuário fecha o aplicativo com um swipe, o sistema o descarrega por falta de memória ou ocorre uma falha
  • Inicialização a frio — o aplicativo inicia do zero, todos os objetos são criados novamente, o estado não é restaurado do cache
  • Inicialização a quente — o aplicativo estava em Suspended e retorna ao Active sem inicialização completa

Not Running — o que é esse estado

Not Running é o estado básico do ciclo de vida de um aplicativo móvel no qual ele não está carregado na RAM do dispositivo e não consome recursos do sistema. No iOS e Android, esse estado significa a ausência completa de processos e threads associados ao aplicativo. O usuário vê o ícone do aplicativo na tela inicial, mas o próprio aplicativo não está ativo e não está na lista de aplicativos recentes.

Quando o usuário toca no ícone do aplicativo, o sistema cria um novo processo, carrega o código executável na memória e inicializa todas as estruturas de dados necessárias. Esse processo é chamado de inicialização a frio (cold start) e é o que mais consome recursos em termos de tempo de carregamento.

O sistema pode mover o aplicativo para Not Running a partir de qualquer outro estado. Se o aplicativo estiver em segundo plano ou suspenso, o sistema operacional tem o direito de descarregá-lo quando não houver RAM suficiente para tarefas de maior prioridade — por exemplo, para um aplicativo ativo em primeiro plano.

O desenvolvedor deve considerar que o aplicativo pode ser encerrado pelo sistema a qualquer momento quando estiver em segundo plano. Isso significa que todos os dados não salvos podem ser perdidos. Portanto, é de vital importância salvar o estado em armazenamentos chave-valor (UserDefaults, SharedPreferences) ou em um banco de dados local durante as transições de Active para Background.

Como o sistema determina qual aplicativo descarregar

O iOS usa prioridades com base no estado atual do aplicativo: Active tem a maior prioridade, seguido por Inactive, Background, Suspended e, finalmente, Not Running — a menor prioridade. O Android usa uma hierarquia de processos semelhante: o processo em primeiro plano tem prioridade OOM_ADJ = 0, processo Visible = 100, processo Service = 200, processo Background = 300, processo Empty = 400. Quanto maior o valor, maior a probabilidade de o processo ser encerrado quando a memória estiver baixa.

PlataformaEstadoPrioridade de descargaDescrição
iOSNot RunningMais altaAplicativo não carregado — não consome recursos do sistema
iOSSuspendedAltaAplicativo na memória mas sem executar código — primeiro alvo de descarga
iOSBackgroundMédiaAplicativo executando tarefa em segundo plano — descarregado após tempo limite
iOSActiveBaixaAplicativo ativo — descarregado apenas sob pressão crítica de memória
AndroidEmpty ProcessMais altaProcesso sem componentes ativos — removido primeiro
AndroidBackground ProcessAltaProcesso em segundo plano sem Activity visível
AndroidForeground ServiceBaixaServiço com notificação — raramente encerrado
AndroidForeground ProcessMínimaActivity ativo — encerrado por último

Inicialização a frio e a quente de um aplicativo

Inicialização a frio (cold start) ocorre quando o aplicativo transita de Not Running diretamente para Active. O sistema cria um novo processo, carrega as classes, inicializa os campos estáticos, cria a thread principal e inicia o framework de UI. No iOS, isso significa chamar application(_:didFinishLaunchingWithOptions:), no Android — chamar Application.onCreate() e Activity.onCreate(). O tempo de inicialização a frio pode variar de 200 ms a vários segundos, dependendo da complexidade do aplicativo.

Inicialização a quente (warm start ou hot start) — o aplicativo estava no estado Suspended e retoma sem um recarregamento completo. O sistema restaura a última pilha de UI da memória, e o usuário continua trabalhando do mesmo ponto. A inicialização a quente é significativamente mais rápida que a inicialização a frio porque a maior parte do código já está carregada na memória. No iOS, uma inicialização a quente não chama application(_:didFinishLaunchingWithOptions:), apenas applicationWillEnterForeground e applicationDidBecomeActive.

A diferença entre inicialização a frio e a quente é crítica para a experiência do usuário. Durante uma inicialização a frio, o desenvolvedor deve garantir que o início ocorra o mais rápido possível — inicialização preguiçosa de módulos, carregamento adiado de recursos pesados, minimização do trabalho na thread principal na inicialização. O Google recomenda uma inicialização a frio de no máximo 500 ms, a Apple — no máximo 400 ms para iOS.

kotlin
// Medição do tempo de inicialização a frio no Android
class App : Application() {
    private var startTime: Long = 0L

    override fun onCreate() {
        super.onCreate()
        startTime = System.currentTimeMillis()
    }

    fun getStartupTime(): Long {
        return System.currentTimeMillis() - startTime
    }
}

// Iniciar Activity com inicialização preguiçosa
class MainActivity : AppCompatActivity() {
    private val viewModel: MainViewModel by lazy {
        ViewModelProvider(this).get(MainViewModel::class.java)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        // Apenas o mínimo necessário para o primeiro quadro
        setupNavigation()
    }

    override fun onPostCreate(savedInstanceState: Bundle?) {
        super.onPostCreate(savedInstanceState)
        // Inicialização pesada após a renderização
        initializeHeavyModules()
    }
}

O exemplo mostra a medição do tempo de inicialização a frio no Android. Application.onCreate() é chamado ao transitar de Not Running para Active. O timestamp é registrado no início do processo. O Activity usa inicialização preguiçosa por meio de um delegado lazy para evitar bloquear o primeiro quadro. onPostCreate é o local ideal para inicializar módulos pesados, pois a UI já foi renderizada.

Not Running no iOS: Swift e AppDelegate

No iOS, o Not Running é gerenciado através do protocolo UIApplicationDelegate. Métodos principais: application(_:didFinishLaunchingWithOptions:) é chamado após uma inicialização a frio, applicationWillTerminate(_:) é chamado antes do usuário encerrar o aplicativo. No entanto, o sistema pode encerrar o aplicativo sem chamar applicationWillTerminate — por exemplo, durante um encerramento de emergência ou pressão de memória. O iOS não garante que este método será chamado, portanto, os dados devem ser salvos em applicationDidEnterBackground.

Cenários de transição para Not Running no iOS

O usuário pode encerrar manualmente o aplicativo com um swipe no App Switcher. O sistema pode descarregar o aplicativo da memória enquanto ele está em segundo plano. O aplicativo pode falhar. Em todos os casos, todos os objetos criados durante a inicialização são destruídos. O estado que não foi salvo é perdido para sempre. No iOS 13+, é recomendado usar NSUserActivity ou o mecanismo de restauração de estado através de UIApplication.stateRestorationIdentifier para preservar o estado.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // Inicialização a frio: aplicativo transitou de Not Running
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Inicializando o conjunto mínimo de serviços
        setupAnalytics()
        configureAppearance()
        return true
    }

    // Aplicativo encerra — apenas fechamento manual
    func applicationWillTerminate(
        _ application: UIApplication
    ) {
        saveCriticalData()
    }

    // Salvando dados antes de ir para segundo plano
    func applicationDidEnterBackground(
        _ application: UIApplication
    ) {
        saveApplicationState()
    }

    private func saveCriticalData() {
        UserDefaults.standard.synchronize()
    }

    private func saveApplicationState() {
        let state = ["lastScreen": "main", "timestamp": Date()]
        try? NSKeyedArchiver.archivedData(
            withRootObject: state,
            requiringSecureCoding: true
        )
    }
}

O código demonstra o tratamento correto do Not Running no iOS. applicationWillTerminate só é chamado quando o usuário encerra manualmente o aplicativo. O salvamento de dados críticos é duplicado em applicationDidEnterBackground, pois este método tem a garantia de ser chamado antes de ir para segundo plano. A restauração de estado permite salvar a pilha de UI para recuperação posterior durante uma inicialização a frio.

Not Running no Android: Kotlin e processo

No Android, Not Running significa que o processo do aplicativo não existe. O sistema Linux subjacente ao Android gerencia processos através do mecanismo Zygote. Quando um aplicativo é iniciado, o Zygote bifurca um novo processo, carrega o Dalvik/ART e chama Application.onCreate(). O Android não tem um equivalente direto do applicationWillTerminate — o sistema pode encerrar o processo a qualquer momento sem aviso.

Ciclo de vida do processo Android

Quando um Activity é chamado pela primeira vez, o sistema cria o processo, Application e Activity através da cadeia onCreate → onStart → onResume. Se o usuário pressionar Voltar, o Activity é destruído (onDestroy), e o processo pode ser encerrado pelo sistema. Uma diferença fundamental do iOS: no Android, o processo pode continuar existindo mesmo sem Activities ativos — por exemplo, se um Foreground Service estiver em execução ou houver um BroadcastReceiver ativo.

kotlin
// Tratamento de Not Running via SavedStateHandle no ViewModel
class MainViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    companion object {
        private const val KEY_LAST_SCREEN = "last_screen"
        private const val KEY_USER_DATA = "user_data"
    }

    fun saveCurrentState(screen: String, data: String) {
        savedStateHandle[KEY_LAST_SCREEN] = screen
        savedStateHandle[KEY_USER_DATA] = data
    }

    fun restoreState(): AppState? {
        val screen = savedStateHandle.get<String>(KEY_LAST_SCREEN)
        val data = savedStateHandle.get<String>(KEY_USER_DATA)
        return if (screen != null && data != null) {
            AppState(screen, data)
        } else null
    }
}

// Application — o primeiro callback após Not Running
class MyApplication : Application() {

    override fun onCreate() {
        super.onCreate()
        initCrashReporter()
        initDependencyInjection()
    }
}

SavedStateHandle é um componente do Android Architecture Components que salva automaticamente o estado durante uma transição para Not Running e o restaura em uma inicialização a frio. Um ViewModel criado através do ViewModelProvider sobrevive à rotação da tela e à destruição do Activity. Quando o processo é encerrado, os dados do SavedStateHandle são serializados em um Bundle e salvos no estado de instância salvo.

Motivos para a transição para Not Running

Not Running ocorre por vários motivos. O usuário fecha manualmente o aplicativo. O sistema descarrega o aplicativo devido à baixa memória. O aplicativo falha com uma exceção. No Android, o sistema pode encerrar o processo durante uma atualização em massa de aplicativos ou reinicialização do dispositivo. O iOS pode encerrar o aplicativo quando uma tarefa em segundo plano expira (geralmente 30 segundos).

MotivoiOSAndroidPode ser evitado
Fechamento manual pelo usuárioSwipe no App SwitcherSwipe dos RecentsNão — ação do usuário
Baixa memóriaAtivação de aviso de memóriaonTrimMemory / LMKParcialmente — otimização de memória
Falha do aplicativoNSException / sinalUncaughtException / ANRSim — tratamento de erros e relatório de falhas
Tempo limite de tarefa em segundo plano30 seg para tarefa em segundo plano10 min para JobSchedulerSim — agendamento correto de tarefas
Reinicialização do SOapplicationWillTerminate chamadoBroadcast ACTION_SHUTDOWNNão — evento do sistema
Atualização do aplicativoNão ocorre (iOS Sandbox)Processo encerrado na atualização APKNão — atualização do sistema

Como diagnosticar uma transição para Not Running

Para iOS, use o registro no console em applicationWillTerminate e applicationDidFinishLaunching. Adicione uma flag no UserDefaults a cada inicialização — se a flag estiver faltando na próxima inicialização, o aplicativo foi encerrado incorretamente. No Android, use ActivityManager.isBackgroundRestricted() para verificar se o aplicativo pode executar tarefas em segundo plano. Além disso, monitore onTrimMemory(TRIM_MEMORY_COMPLETE) — este é um sinal de que o processo será encerrado.

Melhores práticas para trabalhar com Not Running

Primeira regra — nunca presuma que applicationWillTerminate ou onDestroy serão chamados. Salve dados criticamente importantes em cada transição de Active para Background. Use armazenamentos chave-valor para configurações simples e SQLite/Room para dados estruturados.

Segunda regra — meça o tempo de inicialização a frio e otimize-o. Inicialização preguiçosa, minimização do trabalho na thread principal, pré-carregamento de recursos, uso da API SplashScreen — tudo isso melhora a percepção do tempo de inicialização. O Google recomenda uma inicialização a frio de menos de 200 ms para uma excelente experiência do usuário.

Terceira regra — implemente a Restauração de Estado. No iOS, use UIApplication.stateRestorationIdentifier e NSUserActivity. No Android, use SavedStateHandle no ViewModel combinado com onSaveInstanceState. Isso permitirá que o usuário continue trabalhando do mesmo ponto após uma reinicialização do aplicativo.

Quarta regra — lide com launchOptions e Intent com os quais o aplicativo foi iniciado após Not Running. Deep links, notificações push, links universais — todos são passados através dos parâmetros de inicialização. O desenvolvedor deve extrair corretamente esses dados e direcionar o usuário para a tela apropriada.

swift
// Tratamento de deep link após inicialização a frio
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    // Verificando se uma notificação chegou
    if let notification = launchOptions?[.remoteNotification] as? [String: Any] {
        handleNotification(notification)
    }
    // Verificando deep link
    if let url = launchOptions?[.url] as? URL {
        handleDeepLink(url)
    }
    return true
}

private func handleDeepLink(_ url: URL) {
    guard let components = URLComponents(url: url, resolvingAgainstBaseURL: false),
          let screenId = components.queryItems?.first(where: { $0.name == "screen" })?.value
    else { return }
    openScreen(screenId)
}

O código mostra o tratamento dos parâmetros de inicialização em uma inicialização a frio do iOS. launchOptions contém os dados com os quais o sistema iniciou o aplicativo. Notificações, deep links e links universais são passados através deste dicionário. O desenvolvedor deve lidar corretamente com todos os cenários possíveis de inicialização para garantir uma experiência de usuário perfeita.

Perguntas frequentes

O que acontece com os dados ao fazer a transição para Not Running?

Os dados que foram salvos no armazenamento persistente (UserDefaults, Core Data, SharedPreferences, Room) são preservados. Os dados na RAM — variáveis, cache, estado do ViewModel sem SavedStateHandle — são perdidos irreversivelmente. Portanto, é de vital importância salvar o estado do aplicativo em cada transição para Background.

Como distinguir uma inicialização a frio de uma a quente no iOS?

Durante uma inicialização a frio, application(_:didFinishLaunchingWithOptions:) é chamado. Durante uma inicialização a quente (retorno do Suspended), este método não é chamado — apenas applicationWillEnterForeground e applicationDidBecomeActive são acionados. Se você precisar executar uma ação apenas em uma inicialização a frio, defina uma flag no didFinishLaunchingWithOptions.

Um aplicativo Android pode estar em Not Running com um Service ativo?

Sim. Um Foreground Service com uma notificação persistente impede que o sistema encerre o processo, mesmo que todos os Activities sejam destruídos. Um Background Service (startService sem foreground) pode ser interrompido pelo sistema a qualquer momento. Um Service em execução significa que o processo existe, e isso não é mais Not Running.

Como emular Not Running em um simulador?

No simulador iOS, encerre o aplicativo através do App Switcher (Cmd+Shift+H duas vezes, swipe para cima). No emulador Android, use adb shell am force-stop com.example.app ou o botão Stop no Logcat. Depois disso, inicie o aplicativo novamente — será uma inicialização a frio limpa a partir do Not Running.

O que é kill-switch no contexto de Not Running?

Kill-switch é um comando de servidor para encerramento de emergência do aplicativo. É usado em aplicativos bancários e corporativos para bloqueio remoto de acesso. Se o aplicativo receber um comando kill, na próxima inicialização a frio ele bloqueia a UI e solicita reautenticação. No iOS, um kill-switch é implementado através de notificações remotas com uma flag de bloqueio.

Resumo

  • Not Running — o estado inicial e final do ciclo de vida, o aplicativo não está carregado na memória e não executa código
  • Inicialização a frio — reinicialização completa do aplicativo a partir do Not Running, requer inicializar todos os componentes do zero
  • Inicialização a quente — retorno do Suspended, não chama didFinishLaunchingWithOptions ou Application.onCreate
  • Salvamento de dados — é criticamente importante realizar ao fazer a transição para Background, pois Not Running pode ocorrer a qualquer momento
  • iOS — applicationWillTerminate não é garantido, o estado é salvo via UserDefaults ou restauração de estado
  • Android — o processo pode ser encerrado a qualquer momento, SavedStateHandle no ViewModel salva o estado automaticamente
  • Otimização da inicialização — inicialização preguiçosa, trabalho mínimo na thread principal, API SplashScreen para um primeiro quadro rápido

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