Cuando te pones a desarrollar una aplicación para Android, te das cuenta de que no es como programar para un ordenador donde abres un programa y ya está. En el móvil, la cosa cambia totalmente porque el usuario salta de una app a otra constantemente, recibe llamadas que cortan la navegación o gira la pantalla, lo que obliga al sistema a gestionar la memoria de forma muy agresiva para que el dispositivo no se quede colgado.
Básicamente, una Activity es la pieza fundamental que representa una pantalla con la que el usuario puede interactuar. Pero para que la experiencia sea fluida y la app no se cierre de golpe o pierda los datos, Android utiliza un sistema de máquinas de estados. A través de una serie de métodos llamados devoluciones de llamada, la actividad nos avisa en qué punto de su vida se encuentra, permitiéndonos decidir cuándo pausar un vídeo, guardar un borrador o liberar la cámara para que otra aplicación la use.
El mapa de los estados: ¿Cómo funciona el flujo?
Para entender esto, hay que imaginar que la Activity atraviesa un camino desde que nace hasta que es eliminada por el sistema. No es un camino lineal, ya que la actividad puede ir y volver entre estados según lo que haga el usuario. El sistema invoca métodos específicos que empiezan por el prefijo «on» para indicarnos que hemos cambiado de etapa.
El arranque: onCreate y onStart
Todo empieza con el método onCreate. Esta es la fase del «huevo», donde se realiza la configuración básica que solo ocurre una vez. Aquí es donde vinculamos los datos a las vistas, asociamos el ViewModel o definimos el diseño de la interfaz. Es fundamental llamar a la superclase para que la Activity se cree correctamente. Una vez terminado esto, entramos en onStart, que es el momento en que la app se hace visible para el usuario, aunque todavía no sea interactiva. Es el lugar ideal para inicializar el código que mantiene la interfaz activa.
La interacción real: onResume
Cuando la actividad pasa al primer plano y el usuario ya puede tocar botones o escribir, se dispara el método onResume. En este estado, la app tiene el foco total de atención. Si el usuario recibe una llamada o abre un diálogo semi-transparente, la Activity saldrá de este estado. Por eso, es recomendable usar este método para reiniciar componentes que liberamos durante la pausa, como la vista previa de una cámara, asegurando que todo funcione cuando el usuario regrese.
La retirada parcial: onPause
El método onPause es la primera señal de que el usuario está abandonando la pantalla. Ojo, que esto no significa que la Activity se vaya a destruir. Puede que la app siga siendo visible, como ocurre en el modo de pantalla dividida o multiventana, pero ya no tiene el foco. Es el sitio perfecto para pausar animaciones o detener el uso de sensores como el GPS para no fundir la batería. Eso sí, no conviene hacer tareas pesadas aquí, como guardar datos en una base de datos, porque este método debe ejecutarse muy rápido para no bloquear el sistema.
La invisibilidad total: onStop y onRestart
Cuando la pantalla ya no se ve absolutamente nada, entramos en onStop. Aquí es donde debemos liberar recursos que no sirven de nada si el usuario no está viendo la app. Si necesitamos realizar guardados intensivos en la CPU o persistir datos en el almacenamiento local, este es el momento más adecuado. Si el usuario decide volver a la app desde la lista de recientes, el sistema no vuelve a empezar desde cero, sino que llama a onRestart y luego pasa por onStart y onResume, recuperando la actividad justo donde se quedó.
El final del camino: onDestroy
Finalmente, llegamos a onDestroy. Este método se ejecuta justo antes de que la Activity sea eliminada de la memoria. Puede pasar porque el usuario cerró la app definitivamente o porque el sistema decidió matarla debido a un cambio de configuración, como rotar la pantalla de vertical a horizontal. Es la última oportunidad para limpiar hilos o cerrar conexiones que podrían causar fugas de memoria si se dejaran abiertas.
Gestión de memoria y la supervivencia de los datos
Android es muy pragmático: si necesita RAM para una aplicación que tienes en primer plano, no dudará en matar procesos en segundo plano. La probabilidad de que tu app sea eliminada depende de su estado: una actividad detenida (Stopped) es mucho más vulnerable que una que está reanudada (Resumed). Por eso es vital implementar estrategias de guardado.
El problema de la rotación de pantalla
Mucha gente se sorprende al ver que, al girar el móvil, los datos que el usuario había escrito desaparecen. Esto ocurre porque la rotación provoca la destrucción y recreación total de la Activity. Para evitar este dolor de cabeza, existen herramientas como rememberSaveable en Jetpack Compose, que permite que la IU conserve estados ligeros automáticamente, o el uso de ViewModels, que mantienen la lógica de negocio separada del ciclo de vida de la vista.
Navegación moderna y arquitectura
Hoy en día, la recomendación es utilizar una arquitectura de una sola actividad. En lugar de lanzar una Activity nueva para cada pantalla, se usa un solo contenedor y el componente de Navigation para intercambiar pantallas componibles. Esto simplifica enormemente la gestión del ciclo de vida, ya que no tenemos que coordinar tantas transiciones complejas entre diferentes instancias de Activity.
El dominio de estas transiciones permite que una aplicación sea robusta, evitando que se cierre inesperadamente cuando llega una llamada y asegurando que el progreso del usuario se mantenga intacto independientemente de si rota el dispositivo o cambia de aplicación, optimizando así el rendimiento general y la experiencia de uso. Comparte la información para que otros usuarios conozcan del tema.
Continúar leyendo...