Warm Start: esencia, inicio en caliente y optimización en Android

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

Warm Start es un escenario de inicio de una aplicación Android en el que el proceso de la aplicación ya existe en la memoria (por ejemplo, después de minimizarla), pero la Activity fue destruida por el sistema para ahorrar recursos. Application.onCreate ya se ejecutó, las clases están cargadas, pero la UI se crea de nuevo. Según Google, 2024, Warm Start toma de 200 a 800 ms y representa aproximadamente el 40% de todos los inicios en dispositivos con 4 GB de RAM.

Puntos clave

  • Warm Start — inicio de una aplicación con un proceso existente, pero sin una Activity en la memoria
  • Diferencia de Cold Start: Application.onCreate no se ejecuta, las clases ya están cargadas
  • Tiempo Warm Start toma de 200 a 800 ms frente a 1–5 segundos para Cold Start
  • Escenarios: regreso a la aplicación después de varias horas, eliminación de Activity por OOM-killer
  • Optimización se centra en preservar el estado de la Activity y el almacenamiento en caché de datos

Qué es Warm Start

Warm Start es un estado entre Cold Start y Hot Start: el proceso de la aplicación existe en la memoria (a veces en la caché de fondo de Linux), pero la Activity no está activa y se creará de nuevo. Cuando Android se queda sin RAM, puede expulsar la Activity de la pila, dejando el proceso vivo. Cuando el usuario regresa a la aplicación, ocurre un Warm Start: se crea una nueva instancia de Activity, se ejecutan los métodos del ciclo de vida onCreate → onStart → onResume, pero se omiten Application.onCreate y la carga de clases.

Causas de Warm Start

Android decide expulsar la Activity según la prioridad del proceso (rango de importancia). Una Activity en segundo plano (nivel PROCESS_STATE_IMPORTANT_FOREGROUND o PROCESS_STATE_TOP_SLEEPING) puede ser destruida entre 5 y 30 minutos después de minimizar la aplicación, dependiendo de la RAM disponible. En dispositivos con 3 GB de RAM, la Activity puede ser expulsada en 10 minutos; en dispositivos con 8 GB de RAM, después de varias horas. Es importante destacar que durante Warm Start, onSaveInstanceState se llama antes de que la Activity sea destruida, y el desarrollador puede guardar el estado de la UI.

Percepción del usuario

El usuario no ve la diferencia entre Warm y Cold Start — simplemente toca el ícono de la aplicación y espera. Sin embargo, durante Warm Start, puede aparecer una pantalla blanca si la aplicación no ha configurado un tema personalizado para la ventana de inicio. Google recomienda establecer un tema personalizado en el manifiesto (Theme.AppCompat.Light o Theme.Material3.DayNight) para la Activity de inicio, para evitar el parpadeo de la pantalla blanca/negra durante Warm Start. En Android 12+, la API SplashScreen también oculta este efecto.

Warm Start vs Cold Start vs Hot Start

Comprender la diferencia entre los tres tipos de inicio es esencial para elegir la estrategia correcta de perfilado y optimización. Cada tipo tiene su propia duración, cuellos de botella y herramientas de medición.

CriterioCold StartWarm StartHot Start
ProcesoSe crea desde ceroExiste en la memoriaExiste en la memoria
Application.onCreateSe ejecutaNo se ejecutaNo se ejecuta
ActivitySe crea desde ceroSe crea desde ceroSe restaura desde la pila
Tiempo1–5 segundos200–800 ms< 200 ms
onCreate ActivityCompletoCompleto (con restauración)Se omite

En la práctica, Warm Start representa del 30% al 60% de todos los inicios de aplicaciones, dependiendo de los hábitos del usuario y la RAM del dispositivo. Los usuarios que mantienen muchas aplicaciones abiertas (multitarea) se encuentran con Warm Start con más frecuencia. Para las redes sociales y mensajeros, Warm Start es el escenario más común, ya que la aplicación está siempre en segundo plano. Para las aplicaciones bancarias, por el contrario, predomina Cold Start (limpieza forzada del proceso por razones de seguridad).

Fases del inicio en caliente

Warm Start consta de tres fases, cada una de las cuales puede medirse y optimizarse. A diferencia de Cold Start, no hay fase de fork ni carga de clases, pero hay una fase de restauración del estado que puede ser costosa.

Fase 1: Ventana de inicio (fondo de ventana)

El sistema verifica si la aplicación tiene un tema para la ventana de inicio. Si no se establece el tema, se muestra una pantalla blanca (o negra, según el sistema). Si se establece el tema, se muestra el fondo del tema. Esta fase toma de 10 a 30 ms, pero es visualmente notable si el tema no coincide con la UI real de la aplicación. Use Theme.Material3.DayNight con un windowBackground personalizado cuyo color coincida con el fondo de la primera pantalla — esto crea un efecto de carga instantánea.

Fase 2: Creación de Activity (restauración)

El sistema llama a onCreate pasando el Bundle savedInstanceState que se guardó en onSaveInstanceState antes de que la Activity fuera destruida. Si la aplicación guardó correctamente el estado (texto de campos, posición de desplazamiento, datos de ViewModel), la restauración ocurre rápidamente. Si no, la Activity comienza desde cero y el usuario ve un cargador mientras los datos se cargan. Punto clave: los objetos ViewModel sobreviven a Warm Start solo si el proceso no fue destruido — durante Warm Start, el ViewModel permanece en la memoria.

Fase 3: Primer fotograma (TTFD)

Después de onCreate, se ejecutan onStart → onResume, y el sistema activa el primer dibujo. TTFD (Time To First Draw) para Warm Start debe ser inferior a 300 ms en un dispositivo de gama media. Si la primera pantalla contiene un RecyclerView complejo con Views pesadas o carga imágenes de la red, TTFD puede exceder el umbral. Use Placeholder y Shimmer para una carga fluida del contenido después del primer fotograma.

Cómo medir Warm Start

Medir Warm Start es más complejo que Cold Start porque necesita simular el estado en el que el proceso está vivo pero la Activity está destruida. El comando ADB estándar con la bandera -S no funciona — mata el proceso. Use enfoques diferentes para Warm Start.

ADB shell am start sin -S

Primero, inicie la aplicación mediante adb shell monkey o toque el ícono, luego minimícela (adb shell input keyevent 3 keyevent HOME). Espere de 5 a 10 segundos para que el sistema pueda expulsar la Activity, luego ejecute adb shell am start -W (sin -S). El comando devolverá un tiempo de inicio más corto que Cold Start. Para reproducibilidad, use un script: iniciar → esperar → home → esperar → iniciar.

bash
# Simulación de Warm Start mediante ADB
$ adb shell am start -W \
    com.example.app/.MainActivity

# Salida (Warm Start):
# ThisTime: 412 ms
# TotalTime: 412 ms
# WaitTime: 423 ms

Macrobenchmark para Warm Start

La biblioteca androidx.benchmark.macro admite la medición de Warm Start. En la prueba, establezca startupMode = StartupMode.WARM — la biblioteca iniciará la aplicación, la minimizará, esperará (retardo configurable) y luego medirá el reinicio. Macrobenchmark realiza de 10 a 20 iteraciones y calcula percentiles. En CI/CD, puede establecer un umbral: si P50 Warm Start supera los 600 ms, la prueba falla. Esto permite rastrear regresiones con cada commit.

Firebase Performance Monitoring

Firebase distingue automáticamente entre Cold y Warm Start según el tiempo desde el último cierre de la aplicación. Si la aplicación se abrió en los últimos 30 minutos, Firebase clasifica el inicio como Warm. En la consola de Firebase, verá gráficos separados para cada tipo de inicio, lo que le permite evaluar la efectividad de las optimizaciones. Por ejemplo, después de implementar la preservación del estado en ViewModel, puede ver una reducción del 30% en el tiempo de Warm Start.

Cómo optimizar Warm Start

La optimización de Warm Start se centra en dos áreas: acelerar Activity.onCreate y la restauración adecuada del estado. Dado que Application.onCreate y la carga de clases ya se completaron, el principal cuello de botella es el código de UI de la primera pantalla.

Restauración asíncrona del estado

Si el estado guardado (savedInstanceState) contiene datos que necesitan deserialización (Bitmap, String, JSON), hágalo en un hilo de fondo. En lugar de leer directamente del Bundle en onCreate, inicie una corrutina y muestre una pantalla shimmer. En la práctica, la deserialización de Bundle en un dispositivo de gama media toma de 20 a 100 ms — parece poco, pero para Warm Start, esto es del 10 al 50% del tiempo total. Use el Saved State Module de Jetpack, que guarda y restaura automáticamente el estado de ViewModel en el Bundle o la base de datos.

Optimización de setContentView

La inflación del diseño XML es una de las etapas más costosas de Warm Start. Si la primera pantalla usa un CoordinatorLayout complejo con AppBar, CollapsingToolbar, NestedScrollView más tres RecyclerViews, el tiempo de inflación puede alcanzar los 300 ms. Soluciones: use ConstraintLayout para una jerarquía plana, aplique ViewStub para las secciones no visibles al inicio (bottom sheet, dialog), active la inflación asíncrona para fragmentos pesados mediante AsyncLayoutInflater. En Jetpack Compose, no se necesita inflación, pero la compilación del árbol de Compose durante Warm Start puede tomar una cantidad de tiempo similar.

Almacenamiento en caché de datos

Durante Warm Start, los datos que la aplicación cargó en la sesión anterior pueden ya estar en caché: base de datos Room, SharedPreferences, caché en memoria en ViewModel. Si su primera pantalla muestra una lista del servidor, verifique la caché al inicio y actualice los datos en segundo plano. Use la estrategia cache-then-network: primero muestre los datos en caché (instantáneamente), luego actualice desde el servidor (asíncronamente). Esto reduce el tiempo percibido de Warm Start a 100–200 ms.

kotlin
// ViewModel con almacenamiento en caché para Warm Start
class FeedViewModel : ViewModel() {
    private val cache = MutableStateFlow<List<Item>>(emptyList())

    init {
        // Primero caché, luego red
        viewModelScope.launch {
            cache.emit(db.getItems()) // Warm Start: datos ya en BD
            cache.emit(api.fetchItems()) // Actualización en segundo plano
        }
    }
}

Preservación del estado durante Warm Start

La preservación adecuada del estado es el factor clave que distingue un buen Warm Start de uno malo. El usuario espera regresar a la aplicación y ver exactamente lo que dejó — incluyendo la posición de desplazamiento, el texto en los campos y las pestañas seleccionadas.

onSaveInstanceState

El sistema llama a onSaveInstanceState cuando la Activity está siendo destruida, pero ANTES de que el proceso pueda ser eliminado. Solo los tipos de datos simples (String, Int, Parcelable, Serializable) se guardan en el Bundle. Para datos complejos, use SavedStateHandle en ViewModel — guarda y restaura automáticamente los campos durante Warm Start. A diferencia de onSaveInstanceState, SavedStateHandle funciona incluso si el proceso sobrevive a Warm Start (ViewModel no se destruye). Ejemplo: para texto en EditText, use SavedStateHandle.getLiveData(“text”) — el texto se guardará y restaurará automáticamente.

ViewModel y Warm Start

Si el proceso no fue eliminado durante Warm Start, el ViewModel permanece en la memoria y no se llama a onCleared. Esto significa que todos los datos cargados en la sesión anterior están disponibles instantáneamente. Sin embargo, si el proceso fue eliminado (dispositivo en suspensión profunda durante más de 30 minutos), el ViewModel se destruye y se crea de nuevo con SavedStateHandle. Para un comportamiento correcto de ViewModel durante Warm Start, use SavedStateHandle con campos que necesiten restaurarse en cualquier escenario. Diferencia: ViewModel con @HiltViewModel soporta SavedStateHandle automáticamente.

MecanismoProceso vivoProceso eliminado
ViewModelDatos en memoriaDestruido, se crea de nuevo
SavedStateHandleDatos en memoriaRestaurado desde Bundle
onSaveInstanceStateSe llama al expulsar ActivityNo se llama
Room DBCaché disponibleCaché disponible (disco)

Guardar la posición de desplazamiento de RecyclerView

Uno de los problemas más comunes de Warm Start — perder la posición de desplazamiento. El usuario se desplazó al elemento 50, minimizó la aplicación, regresó — y ve el inicio de la lista. Solución: guarde layoutManager.onSaveInstanceState (guarda la posición y el desplazamiento del primer elemento visible) y restáurelo en onRestoreInstanceState. También puede guardar la última posición visible en SharedPreferences con una clave de fecha/hora para restaurar rápidamente la posición durante Warm Start.

kotlin
// Guardar la posición de desplazamiento de RecyclerView
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putParcelable(
        "rv_state", binding.recyclerView
            .layoutManager?.onSaveInstanceState()
    )
}

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    savedInstanceState?.getParcelable<Parcelable>("rv_state")
        ?.let { binding.recyclerView.layoutManager?.onRestoreInstanceState(it) }
}

Ejemplos de código para Warm Start

Dos ejemplos prácticos de optimización de Warm Start: uso de SavedStateHandle en ViewModel y restauración asíncrona de datos complejos después del inicio.

ViewModel con SavedStateHandle

SavedStateHandle guarda automáticamente los campos en el Bundle y los restaura durante Warm Start. El campo de perfil de usuario (String, JSON) se restaurará sin solicitudes innecesarias al servidor. Si el proceso fue eliminado, SavedStateHandle carga el último estado guardado desde el Bundle.

kotlin
class ProfileViewModel(
    private val savedStateHandle: SavedStateHandle
) : ViewModel() {

    val profile: StateFlow<Profile?>
        get() = savedStateHandle
            .getStateFlow("profile", null)

    fun loadProfile(id: String) {
        viewModelScope.launch {
            savedStateHandle["profile"] =
                api.getProfile(id)
        }
    }
}

// Warm Start: profile no es null, UI sin cargador
// Después de cargar: profile se actualiza en SavedStateHandle

AsyncLayoutInflater para pantallas pesadas

Si la primera pantalla contiene un diseño complejo (mapa, degradado, varias listas), use AsyncLayoutInflater para inflar elementos pesados en segundo plano. Mientras se infla el diseño, muestre un placeholder con efecto shimmer. Esto es especialmente importante para Warm Start, donde cada milisegundo cuenta. AsyncLayoutInflater se ejecuta en un hilo de fondo y pasa el View listo a un callback en el hilo principal.

kotlin
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // Diseño de marcador de posición para renderizado instantáneo
        setContentView(R.layout.placeholder_shimmer)

        // Carga asíncrona de diseño pesado
        AsyncLayoutInflater(this).inflate(
            R.layout.activity_main_complex,
            findViewById(R.id.container)
        ) { view, resId, parent ->
            parent?.removeAllViews()
            parent?.addView(view)
        }
    }
}

Preguntas frecuentes

¿Puede Warm Start convertirse en Cold Start?

Sí, si en el momento de Warm Start el sistema decide eliminar el proceso de la aplicación (por ejemplo, para liberar memoria para otra aplicación), el inicio se convierte en Cold Start desde cero. Esto ocurre en dispositivos con 2–3 GB de RAM cuando se ejecutan varias aplicaciones simultáneamente. De hecho, Warm Start solo está garantizado durante 10–20 minutos después de minimizar en dispositivos de gama media.

¿Se conserva el ViewModel durante Warm Start?

Sí, si el proceso no fue eliminado, el ViewModel permanece en la memoria y no se llama a onCleared. Esta es una ventaja clave de Warm Start: todos los datos cargados mediante solicitudes de red, el caché en ViewModel — todo está disponible instantáneamente. Si el proceso fue eliminado, el ViewModel se crea de nuevo a través de ViewModelProvider.Factory o @HiltViewModel, y SavedStateHandle restaura los campos guardados.

¿Por qué Warm Start puede ser más lento que Cold Start?

Teóricamente, Warm Start siempre es más rápido que Cold Start, pero en la práctica hay escenarios donde la diferencia es mínima: si Application.onCreate fue ligero (50 ms) y Activity.onCreate es pesado (800 ms), entonces Warm Start (800 ms) es casi igual a Cold Start (850 ms). En este caso, debe optimizar no Application, sino Activity.onCreate — se convierte en el cuello de botella para Warm Start.

¿Cómo afecta la API SplashScreen a Warm Start?

La API SplashScreen en Android 12+ muestra un splash del sistema (icono sobre fondo de color) inmediatamente al inicio — tanto para Cold como para Warm Start. Para Warm Start, el splash se muestra solo durante 100–300 ms, después de lo cual es reemplazado por la UI de la aplicación. SplashScreen no acelera el inicio en sí, pero enmascara el tiempo de creación de Activity, mejorando la percepción.

¿Es necesario optimizar Warm Start si Cold Start ya es rápido?

Sí, porque Warm Start ocurre de 2 a 3 veces más a menudo que Cold Start. Si Cold Start toma 1.2 segundos y Warm Start toma 600 ms, entonces el 40% de los inicios (Warm) todavía toman 0.6 segundos, lo que es notable. Optimizar Warm Start hasta 200–300 ms le da al usuario una sensación de retorno instantáneo. En dispositivos con 6+ GB de RAM, Warm Start puede representar hasta el 80% de todos los inicios, lo que convierte su optimización en una prioridad.

Resumen

  • Warm Start — inicio de una aplicación con un proceso existente, sin una Activity en la memoria, tiempo 200–800 ms
  • Principal diferencia de Cold Start: Application.onCreate no se ejecuta, las clases están cargadas
  • Tres fases de Warm Start: ventana de inicio → creación de Activity → primer fotograma
  • Se mide mediante ADB sin la bandera -S o Macrobenchmark con StartupMode.WARM
  • Optimización: SavedStateHandle, AsyncLayoutInflater, cache-then-network, ConstraintLayout
  • ViewModel se conserva durante Warm Start (proceso vivo) — los datos están disponibles instantáneamente
  • Warm Start representa del 40 al 80% de todos los inicios de aplicaciones

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