Not Running — qué es, el estado inicial del ciclo de vida

Autor: IT Sectr Publicado: 2026-03-03 Tiempo de lectura: 11 min

Not Running — el estado inicial del ciclo de vida de una aplicación móvil cuando aún no se ha iniciado o ya ha finalizado. Descubra cómo iOS y Android gestionan este estado, qué eventos provocan la transición desde Not Running y cómo manejar correctamente el inicio y la finalización de la aplicación en Swift y Kotlin.

Puntos clave

  • Not Running — la aplicación no está cargada en memoria ni ejecuta código; es el punto de entrada y salida del ciclo de vida
  • Inicio — la transición desde Not Running ocurre al tocar el icono de la app, mediante un deep link o una notificación push
  • Finalización — el usuario cierra la aplicación con un deslizamiento, el sistema la descarga por falta de memoria o se produce un bloqueo
  • Arranque en frío — la aplicación se inicia desde cero, todos los objetos se crean de nuevo, el estado no se restaura desde la caché
  • Arranque en caliente — la aplicación estaba en Suspended y vuelve a Active sin inicialización completa

Not Running — qué es este estado

Not Running es el estado básico del ciclo de vida de una aplicación móvil en el que no está cargada en la RAM del dispositivo ni consume recursos del sistema. En iOS y Android, este estado significa la ausencia total de procesos e hilos asociados con la aplicación. El usuario ve el icono de la aplicación en la pantalla de inicio, pero la propia aplicación no está activa ni aparece en la lista de aplicaciones recientes.

Cuando el usuario toca el icono de la aplicación, el sistema crea un nuevo proceso, carga el código ejecutable en memoria e inicializa todas las estructuras de datos necesarias. Este proceso se llama arranque en frío (cold start) y es el que más recursos consume en términos de tiempo de carga.

El sistema puede mover la aplicación a Not Running desde cualquier otro estado. Si la aplicación está en segundo plano o suspendida, el sistema operativo tiene derecho a descargarla cuando no haya suficiente RAM para tareas de mayor prioridad, por ejemplo, para una aplicación activa en primer plano.

El desarrollador debe considerar que la aplicación puede ser finalizada por el sistema en cualquier momento cuando esté en segundo plano. Esto significa que todos los datos no guardados pueden perderse. Por lo tanto, es de vital importancia guardar el estado en almacenes clave-valor (UserDefaults, SharedPreferences) o en una base de datos local durante las transiciones de Active a Background.

Cómo determina el sistema qué aplicación descargar

iOS utiliza prioridades basadas en el estado actual de la aplicación: Active tiene la prioridad más alta, seguido de Inactive, Background, Suspended y, finalmente, Not Running — la prioridad más baja. Android utiliza una jerarquía de procesos similar: el proceso en primer plano tiene prioridad OOM_ADJ = 0, proceso Visible = 100, proceso Service = 200, proceso Background = 300, proceso Empty = 400. Cuanto mayor es el valor, más probable es que el proceso se finalice cuando falte memoria.

PlataformaEstadoPrioridad de descargaDescripción
iOSNot RunningMás altaAplicación no cargada — no consume recursos del sistema
iOSSuspendedAltaAplicación en memoria pero sin ejecutar código — primer objetivo de descarga
iOSBackgroundMediaAplicación ejecutando una tarea en segundo plano — se descarga tras tiempo de espera
iOSActiveBajaAplicación activa — se descarga solo con presión crítica de memoria
AndroidEmpty ProcessMás altaProceso sin componentes activos — se elimina primero
AndroidBackground ProcessAltaProceso en segundo plano sin Activity visible
AndroidForeground ServiceBajaServicio con notificación — raramente finalizado
AndroidForeground ProcessMínimaActivity activo — se finaliza al último

Arranque en frío y en caliente de una aplicación

Arranque en frío (cold start) ocurre cuando la aplicación pasa de Not Running directamente a Active. El sistema crea un nuevo proceso, carga las clases, inicializa los campos estáticos, crea el hilo principal e inicia el framework de UI. En iOS, esto significa llamar a application(_:didFinishLaunchingWithOptions:), en Android — llamar a Application.onCreate() y Activity.onCreate(). El tiempo de arranque en frío puede oscilar entre 200 ms y varios segundos dependiendo de la complejidad de la aplicación.

Arranque en caliente (warm start o hot start) — la aplicación estaba en estado Suspended y se reanuda sin una recarga completa. El sistema restaura la última pila de UI desde la memoria y el usuario continúa trabajando desde el mismo punto. El arranque en caliente es significativamente más rápido que el arranque en frío porque la mayor parte del código ya está cargada en memoria. En iOS, un arranque en caliente no llama a application(_:didFinishLaunchingWithOptions:), solo a applicationWillEnterForeground y applicationDidBecomeActive.

La diferencia entre el arranque en frío y en caliente es crítica para la experiencia del usuario. Durante un arranque en frío, el desarrollador debe asegurarse de que el inicio ocurra lo más rápido posible — inicialización perezosa de módulos, carga diferida de recursos pesados, minimización del trabajo en el hilo principal al iniciar. Google recomienda un arranque en frío de no más de 500 ms, Apple — no más de 400 ms para iOS.

kotlin
// Medición del tiempo de arranque en frío en Android
class App : Application() {
    private var startTime: Long = 0L

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

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

// Inicio de Activity con inicialización perezosa
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)
        // Solo el mínimo necesario para el primer fotograma
        setupNavigation()
    }

    override fun onPostCreate(savedInstanceState: Bundle?) {
        super.onPostCreate(savedInstanceState)
        // Inicialización pesada después del renderizado
        initializeHeavyModules()
    }
}

El ejemplo muestra la medición del tiempo de arranque en frío en Android. Application.onCreate() se llama al pasar de Not Running a Active. La marca de tiempo se registra al iniciar el proceso. El Activity utiliza inicialización perezosa mediante un delegado lazy para no bloquear el primer fotograma. onPostCreate es el lugar óptimo para inicializar módulos pesados, ya que la UI ya se ha renderizado.

Not Running en iOS: Swift y AppDelegate

En iOS, Not Running se gestiona a través del protocolo UIApplicationDelegate. Métodos clave: application(_:didFinishLaunchingWithOptions:) se llama después de un arranque en frío, applicationWillTerminate(_:) se llama antes de que el usuario finalice la aplicación. Sin embargo, el sistema puede finalizar la aplicación sin llamar a applicationWillTerminate — por ejemplo, durante una finalización de emergencia o presión de memoria. iOS no garantiza que este método se llame, por lo que los datos deben guardarse en applicationDidEnterBackground.

Escenarios de transición a Not Running en iOS

El usuario puede finalizar manualmente la aplicación con un deslizamiento en el App Switcher. El sistema puede descargar la aplicación de la memoria mientras está en segundo plano. La aplicación puede bloquearse. En todos los casos, todos los objetos creados durante el inicio se destruyen. El estado que no se guardó se pierde para siempre. En iOS 13+, se recomienda usar NSUserActivity o el mecanismo de restauración de estado a través de UIApplication.stateRestorationIdentifier para preservar el estado.

swift
import UIKit

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    // Arranque en frío: la aplicación pasó de Not Running
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        // Inicialización del conjunto mínimo de servicios
        setupAnalytics()
        configureAppearance()
        return true
    }

    // La aplicación finaliza — solo cierre manual
    func applicationWillTerminate(
        _ application: UIApplication
    ) {
        saveCriticalData()
    }

    // Guardar datos antes de ir a 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
        )
    }
}

El código muestra el manejo correcto de Not Running en iOS. applicationWillTerminate solo se llama cuando el usuario finaliza manualmente la aplicación. El guardado de datos críticos se duplica en applicationDidEnterBackground ya que este método está garantizado para llamarse antes de ir a segundo plano. La restauración de estado permite guardar la pila de UI para su posterior recuperación durante un arranque en frío.

Not Running en Android: Kotlin y proceso

En Android, Not Running significa que el proceso de la aplicación no existe. El sistema Linux subyacente de Android gestiona los procesos mediante el mecanismo Zygote. Cuando se inicia una aplicación, Zygote bifurca un nuevo proceso, carga Dalvik/ART y llama a Application.onCreate(). Android no tiene un equivalente directo de applicationWillTerminate — el sistema puede finalizar el proceso en cualquier momento sin previo aviso.

Ciclo de vida del proceso en Android

Cuando se llama a un Activity por primera vez, el sistema crea el proceso, Application y Activity a través de la cadena onCreate → onStart → onResume. Si el usuario presiona Atrás, el Activity se destruye (onDestroy) y el sistema puede finalizar el proceso. Una diferencia clave con iOS: en Android, el proceso puede seguir existiendo incluso sin Activities activos — por ejemplo, si se ejecuta un Foreground Service o hay un BroadcastReceiver activo.

kotlin
// Manejo de Not Running mediante SavedStateHandle en 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 — la primera devolución de llamada después de Not Running
class MyApplication : Application() {

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

SavedStateHandle es un componente de Android Architecture Components que guarda automáticamente el estado durante una transición a Not Running y lo restaura en un arranque en frío. Un ViewModel creado a través de ViewModelProvider sobrevive a la rotación de pantalla y a la destrucción del Activity. Cuando el proceso finaliza, los datos de SavedStateHandle se serializan en un Bundle y se guardan en el estado de instancia guardado.

Razones para la transición a Not Running

Not Running ocurre por varias razones. El usuario cierra manualmente la aplicación. El sistema descarga la aplicación por falta de memoria. La aplicación se bloquea con una excepción. En Android, el sistema puede finalizar el proceso durante una actualización masiva de aplicaciones o un reinicio del dispositivo. iOS puede finalizar la aplicación cuando una tarea en segundo plano agota el tiempo de espera (generalmente 30 segundos).

RazóniOSAndroidSe puede prevenir
Cierre manual por el usuarioDeslizar en App SwitcherDeslizar desde RecentsNo — acción del usuario
Falta de memoriaActivación de aviso de memoriaonTrimMemory / LMKParcialmente — optimización de memoria
Bloqueo de la aplicaciónNSException / señalUncaughtException / ANRSí — manejo de errores y reporte de bloqueos
Tiempo de espera de tarea en segundo plano30 seg para tarea en segundo plano10 min para JobSchedulerSí — programación correcta de tareas
Reinicio del SOSe llama a applicationWillTerminateBroadcast ACTION_SHUTDOWNNo — evento del sistema
Actualización de la aplicaciónNo ocurre (iOS Sandbox)El proceso finaliza al actualizar APKNo — actualización del sistema

Cómo diagnosticar una transición a Not Running

Para iOS, use el registro en consola en applicationWillTerminate y applicationDidFinishLaunching. Agregue una bandera en UserDefaults en cada inicio — si la bandera falta en el próximo inicio, la aplicación se finalizó incorrectamente. En Android, use ActivityManager.isBackgroundRestricted() para verificar si la aplicación puede ejecutar tareas en segundo plano. También, supervise onTrimMemory(TRIM_MEMORY_COMPLETE) — esta es una señal de que el proceso será finalizado.

Mejores prácticas para trabajar con Not Running

Primera regla — nunca asuma que se llamará a applicationWillTerminate u onDestroy. Guarde los datos críticamente importantes en cada transición de Active a Background. Use almacenes clave-valor para configuraciones simples y SQLite/Room para datos estructurados.

Segunda regla — mida el tiempo de arranque en frío y optimícelo. Inicialización perezosa, minimización del trabajo en el hilo principal, precarga de recursos, uso de la API SplashScreen — todo esto mejora la percepción del tiempo de inicio. Google recomienda un arranque en frío de menos de 200 ms para una excelente experiencia de usuario.

Tercera regla — implemente la Restauración de Estado. En iOS, use UIApplication.stateRestorationIdentifier y NSUserActivity. En Android, use SavedStateHandle en ViewModel combinado con onSaveInstanceState. Esto permitirá al usuario continuar trabajando desde el mismo punto después de un reinicio de la aplicación.

Cuarta regla — maneje launchOptions e Intent con los que se inició la aplicación después de Not Running. Deep links, notificaciones push, enlaces universales — todos se pasan a través de los parámetros de inicio. El desarrollador debe extraer correctamente estos datos y dirigir al usuario a la pantalla correspondiente.

swift
// Manejo de deep link después de un arranque en frío
func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
    // Verificar si llegó una notificación
    if let notification = launchOptions?[.remoteNotification] as? [String: Any] {
        handleNotification(notification)
    }
    // Verificar 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)
}

El código muestra el manejo de los parámetros de inicio en un arranque en frío de iOS. launchOptions contiene los datos con los que el sistema inició la aplicación. Las notificaciones, deep links y enlaces universales se pasan a través de este diccionario. El desarrollador debe manejar correctamente todos los escenarios de inicio posibles para garantizar una experiencia de usuario fluida.

Preguntas frecuentes

¿Qué sucede con los datos al hacer la transición a Not Running?

Los datos que se guardaron en el almacenamiento persistente (UserDefaults, Core Data, SharedPreferences, Room) se conservan. Los datos en RAM — variables, caché, estado del ViewModel sin SavedStateHandle — se pierden irreversiblemente. Por lo tanto, es de vital importancia guardar el estado de la aplicación en cada transición a Background.

¿Cómo distinguir un arranque en frío de uno en caliente en iOS?

Durante un arranque en frío, se llama a application(_:didFinishLaunchingWithOptions:). Durante un arranque en caliente (regreso de Suspended), este método no se llama — solo se activan applicationWillEnterForeground y applicationDidBecomeActive. Si necesita realizar una acción solo en un arranque en frío, establezca una bandera en didFinishLaunchingWithOptions.

¿Puede una aplicación Android estar en Not Running con un Service activo?

Sí. Un Foreground Service con una notificación persistente evita que el sistema finalice el proceso, incluso si todos los Activities están destruidos. Un Background Service (startService sin foreground) puede ser detenido por el sistema en cualquier momento. Un Service en ejecución significa que el proceso existe, y esto ya no es Not Running.

¿Cómo emular Not Running en un simulador?

En el simulador de iOS, finalice la aplicación a través del App Switcher (Cmd+Shift+H dos veces, deslizar hacia arriba). En el emulador de Android, use adb shell am force-stop com.example.app o el botón Stop en Logcat. Después de eso, inicie la aplicación de nuevo — será un arranque en frío limpio desde Not Running.

¿Qué es un kill-switch en el contexto de Not Running?

Kill-switch es un comando de servidor para la finalización de emergencia de la aplicación. Se utiliza en aplicaciones bancarias y empresariales para el bloqueo remoto de acceso. Si la aplicación recibe un comando kill, en el próximo arranque en frío bloquea la UI y solicita una nueva autenticación. En iOS, un kill-switch se implementa mediante notificaciones remotas con una bandera de bloqueo.

Resumen

  • Not Running — el estado inicial y final del ciclo de vida, la aplicación no está cargada en memoria y no ejecuta código
  • Arranque en frío — reinicio completo de la aplicación desde Not Running, requiere inicializar todos los componentes desde cero
  • Arranque en caliente — regreso desde Suspended, no llama a didFinishLaunchingWithOptions ni a Application.onCreate
  • Guardado de datos — es críticamente importante realizarlo al hacer la transición a Background, ya que Not Running puede ocurrir en cualquier momento
  • iOS — applicationWillTerminate no está garantizado, el estado se guarda mediante UserDefaults o restauración de estado
  • Android — el proceso puede finalizarse en cualquier momento, SavedStateHandle en ViewModel guarda el estado automáticamente
  • Optimización del inicio — inicialización perezosa, trabajo mínimo en el hilo principal, API SplashScreen para un primer fotograma rápido

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también