El Activity Lifecycle es un conjunto de métodos de devolución de llamada que Android invoca cuando una Activity transiciona entre estados: creación, visibilidad, foco de entrada, pérdida parcial de visibilidad, ocultación total y destrucción. El sistema gestiona el ciclo de vida de cada pantalla de la aplicación, desde el momento en que se llama a onCreate() hasta onDestroy(). Comprender estos estados es un requisito obligatorio para el funcionamiento estable de una aplicación Android, ya que un manejo incorrecto de las transiciones entre métodos provoca fugas de memoria, pérdida de datos del usuario y fallos inesperados. Más información sobre la arquitectura de Android en el artículo general sobre Android.
Puntos clave
El Activity Lifecycle (ciclo de vida de Activity) es una máquina de estados por la que pasa cada pantalla de una aplicación Android desde el momento de su creación hasta su destrucción completa. El sistema Android gestiona este proceso basándose en las acciones del usuario: abrir la aplicación, minimizar, rotar la pantalla, responder a una llamada entrante, cambiar entre aplicaciones y cerrar la aplicación.
Comprender el ciclo de vida es esencial para todo desarrollador Android, ya que el sistema puede destruir una Activity en cualquier momento si falta memoria — y la aplicación debe restaurar correctamente su estado. Según Google Android Vitals (2025), las aplicaciones que no gestionan el guardado de estado en onSaveInstanceState() muestran un 42% más de fallos al recrear la Activity.
El ciclo de vida incluye seis métodos callback principales: onCreate(), onStart(), onResume(), onPause(), onStop(), onDestroy(). Adicionalmente existe el método onRestart(), que se llama antes de onStart() cuando una Activity regresa del estado detenido. Cada método tiene un propósito y un tiempo de ejecución estrictamente definidos — el sistema los llama secuencialmente, y el desarrollador puede sobrescribir cualquiera de ellos para implementar su propia lógica.
El ciclo se puede dividir en tres etapas clave: duración completa (onCreate → onDestroy), duración visible (onStart → onStop) y duración en primer plano (onResume → onPause). Comprender estos tres niveles ayuda a distribuir correctamente el código de inicialización y liberación de recursos.
Cada método del ciclo de vida realiza una tarea estrictamente definida. El sistema los llama en un orden fijo, y el desarrollador solo debe sobrescribir los métodos necesarios para la lógica específica. No se recomienda llamar a los métodos del ciclo de vida directamente — esto lo gestiona el Android Runtime.
Una secuencia típica al iniciar una aplicación: onCreate → onStart → onResume. Al pulsar el botón Atrás: onPause → onStop → onDestroy. Al minimizar: onPause → onStop, luego al regresar: onRestart → onStart → onResume.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onStart() {
super.onStart()
}
override fun onResume() {
super.onResume()
}
override fun onPause() {
super.onPause()
}
override fun onStop() {
super.onStop()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onRestart() {
super.onRestart()
}
}
Cada método sobrescrito debe llamar a su versión super — sin esto, el sistema no puede completar correctamente la transición de estado. Esta regla está establecida en la documentación de Android Developers y se verifica mediante las reglas lint de Android Studio.
El primer nivel — duración completa (entire lifetime): el intervalo entre onCreate y onDestroy. Aquí se realiza la inicialización única y la liberación final de recursos globales. El segundo nivel — duración visible (visible lifetime): entre onStart y onStop. La Activity es visible en la pantalla, pero puede estar parcialmente cubierta por otra ventana. El tercer nivel — duración en primer plano (foreground lifetime): entre onResume y onPause. La Activity está en la cima de la pila de tareas e interactúa con el usuario.
onCreate() — el primer y único método obligatorio del ciclo de vida de Activity. El sistema lo llama una vez al crear una instancia de Activity. Este método acepta un parámetro savedInstanceState: Bundle?, que contiene el estado previamente guardado si la Activity se está recreando después de su destrucción — por ejemplo, al rotar la pantalla.
Dentro de onCreate se realizan las siguientes tareas: inicialización de la interfaz de usuario mediante setContentView() con un recurso de layout, vinculación de elementos View mediante findViewById(), configuración de adaptadores para RecyclerView y ViewPager, restauración del estado desde savedInstanceState, inicialización de ViewModel y LiveData, configuración de listeners de clics y gestos. El método debe completarse lo más rápido posible — las operaciones largas aquí bloquean el renderizado del primer fotograma, aumentando el tiempo de inicio de la aplicación.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_profile)
val userNameText: TextView = findViewById(R.id.user_name)
val loadButton: Button = findViewById(R.id.load_button)
if (savedInstanceState != null) {
userNameText.text = savedInstanceState.getString("user_name")
}
loadButton.setOnClickListener {
loadUserProfile()
}
}
Si la Activity se crea por primera vez, savedInstanceState es null. Al recrearse tras una rotación de pantalla, el Bundle contiene los datos guardados en onSaveInstanceState(). La comprobación de null es una práctica estándar para restaurar correctamente la UI sin perder los datos introducidos por el usuario.
onStart() se llama inmediatamente después de onCreate() o después de onRestart(), cuando la Activity se vuelve visible para el usuario. En este estado, la Activity aún no está en primer plano y no puede interactuar con el usuario, pero su interfaz de usuario ya es visible en la pantalla. Por ejemplo, al iniciar una aplicación, el sistema renderiza el primer fotograma de la interfaz entre las llamadas onStart y onResume.
En el método onStart se suelen realizar las siguientes acciones: iniciar animaciones que deben funcionar mientras la Activity sea visible; vincular receptores de difusión (BroadcastReceiver); conectarse a servicios de geolocalización y sensores; actualizar datos desde ViewModel o Room. Aquí también se realiza la vinculación a servicios Bound mediante bindService() si la aplicación utiliza una arquitectura cliente-servidor dentro del proceso.
override fun onStart() {
super.onStart()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
5000L,
10f,
locationListener
)
}
override fun onStop() {
super.onStop()
val locationManager = getSystemService(Context.LOCATION_SERVICE) as LocationManager
locationManager.removeUpdates(locationListener)
}
Regla importante: los recursos conectados en onStart deben liberarse en onStop. Esto garantiza que cuando la Activity no sea visible en la pantalla, no consuma batería ni recursos del sistema. Google Play Store verifica las aplicaciones en busca de fugas de LocationListener y otros servicios del sistema al moderar las actualizaciones.
onResume() — el estado en el que la Activity está en primer plano y lista para interactuar con el usuario. Este es el estado de trabajo de la pantalla: el sistema transfiere el foco de entrada a la Activity, y todos los eventos táctiles, de entrada de teclado y gestos se dirigen a esta pantalla. El método onResume se llama cada vez que la Activity regresa al primer plano — después de que otra Activity finaliza, después de cerrar un cuadro de diálogo, o después de desbloquear el dispositivo.
En onResume se realizan: reanudación de animaciones que se pausaron en onPause; apertura de la cámara y otros recursos exclusivos; registro de listeners de sensores (acelerómetro, giroscopio); inicio de temporizadores y cronómetros para la UI; actualización del contenido de la pantalla con datos actuales. El par onResume/onPause se utiliza para recursos que deben estar activos solo cuando hay foco — por ejemplo, reconocimiento continuo de voz o captura de video.
override fun onResume() {
super.onResume()
cameraHolder.openCamera()
animator.resume()
sensorManager.registerListener(
stepCounter,
sensorManager.getDefaultSensor(Sensor.TYPE_STEP_COUNTER),
SensorManager.SENSOR_DELAY_NORMAL
)
}
override fun onPause() {
super.onPause()
cameraHolder.closeCamera()
animator.pause()
sensorManager.unregisterListener(stepCounter)
}
La diferencia entre onStart y onResume es significativa: una Activity puede ser visible (onStart) pero no activa (onResume) — por ejemplo, cuando se muestra un cuadro de diálogo emergente o una pantalla de bloqueo transparente sobre ella. Es en onResume, no en onStart, donde se deben abrir los recursos exclusivos que requieren acceso exclusivo.
onPause() se llama cuando la Activity pierde el foco de entrada, pero permanece parcialmente visible. Escenarios típicos: apertura de un cuadro de diálogo, pulsación del botón Aplicaciones recientes, llamada entrante, pulsación del botón Inicio (en este caso, onPause será seguido de onStop). El método onPause es el último lugar fiable para guardar datos que el usuario no debe perder.
En onPause se realizan: guardado de borradores de correos electrónicos y formularios en Room o SharedPreferences; detención de animaciones y reproducción de video; cierre de la cámara y liberación de recursos exclusivos; cancelación de operaciones costosas que no sean críticas en segundo plano. El método onPause debe completarse en menos de 100 milisegundos — el sistema bloquea la transición a la siguiente Activity hasta que onPause devuelva el control, y superar el límite provoca ANR (Application Not Responding).
override fun onPause() {
super.onPause()
val editor = SharedPreferences.Manager ...
editor.putString("draft_text", draftEditText.text.toString())
editor.apply()
videoView.pause()
cameraHolder.release()
}
Importante: onPause se ejecuta en el hilo de la UI, por lo que cualquier operación bloqueante como la escritura en la base de datos mediante Room con una consulta síncrona debe reemplazarse por operaciones asíncronas (corrutinas) o ejecutarse en un hilo en segundo plano. Use apply() en lugar de commit() para SharedPreferences — apply escribe datos de forma asíncrona y no bloquea el hilo de la UI.
onStop() se llama cuando la Activity deja de ser visible para el usuario. Esto ocurre en los siguientes casos: la Activity está completamente cubierta por otra Activity; el usuario pulsó el botón Inicio o cambió a otra aplicación; la Activity está finalizando (luego se llamará a onDestroy). En el estado onStop, la Activity permanece en la memoria y conserva todos sus campos — no está destruida, pero tampoco activa.
En onStop se realizan: cancelación de la suscripción de los BroadcastReceiver registrados en onStart; desconexión de servicios Bound; liberación de LocationListener, SensorListener y otros listeners del sistema; detención de operaciones en segundo plano de larga duración que no son necesarias cuando la aplicación está oculta; escritura del estado actual de la UI en un Bundle mediante onSaveInstanceState() si no se hizo en onPause.
override fun onStop() {
super.onStop()
unregisterReceiver(connectivityReceiver)
unbindService(serviceConnection)
if (isChangingConfigurations()) {
Log.d("Lifecycle", "La Activity se recrea debido a la configuración")
}
}
El sistema puede destruir una Activity en estado onStop sin llamar a onDestroy cuando falta memoria. Por lo tanto, todos los datos críticos deben guardarse antes de la transición a onStop. La bandera isChangingConfigurations() permite determinar si la llamada a onStop está relacionada con la rotación de la pantalla — en este caso, la Activity se recreará, no se finalizará.
onDestroy() — el último método del ciclo de vida llamado antes de la destrucción completa de la Activity. El sistema llama a onDestroy en dos casos: la Activity finaliza mediante finish() o el usuario pulsa el botón Atrás; la Activity es destruida por el sistema debido a un cambio de configuración (por ejemplo, rotación de pantalla) y se creará de nuevo. El método onDestroy permite realizar la limpieza final de recursos: desvincular hilos y corrutinas, cerrar cursores y sockets abiertos permanentemente, y liberar memoria nativa a través del NDK.
override fun onDestroy() {
super.onDestroy()
backgroundJob.cancel()
dbHelper.close()
if (isFinishing) {
Log.d("Lifecycle", "La Activity finaliza permanentemente")
} else {
Log.d("Lifecycle", "La Activity se recreará")
}
}
Nota importante: no se garantiza que se llame a onDestroy si el proceso de la aplicación es eliminado por el sistema (out-of-memory kill). Por lo tanto, no se puede confiar en onDestroy para guardar datos — esta tarea se resuelve en onPause o onStop. La propiedad isFinishing permite distinguir la finalización de la Activity mediante finish() de la recreación por cambio de configuración.
onRestart() se llama antes de onStart() cuando una Activity regresa del estado detenido (onStop) al primer plano. Esto ocurre cuando el usuario vuelve a abrir la aplicación desde el menú Aplicaciones recientes o regresa a una Activity pulsando Atrás en una pantalla hija. El método onRestart permite ejecutar una lógica diferente a la de onCreate — por ejemplo, actualizar datos que pueden haber cambiado mientras la Activity estaba oculta.
override fun onRestart() {
super.onRestart()
refreshDataFromNetwork()
Log.d("Lifecycle", "La Activity se reinicia desde la pila")
}
Escenario típico: el usuario abrió la aplicación, cambió a otra tarea y regresó una hora después. En onRestart, la aplicación puede comprobar la relevancia de los datos y, si ha pasado mucho tiempo, sugerir recargar el contenido. Esto mejora la experiencia del usuario y reduce la probabilidad de mostrar información desactualizada.
La rotación de pantalla es el escenario más común de recreación de Activity. Por defecto, Android destruye la Activity actual y crea una nueva con cada cambio de orientación. Si no se guarda el estado, el usuario perderá todos los datos introducidos. Android proporciona dos mecanismos para esto: onSaveInstanceState() para datos serializables y ViewModel para datos que sobreviven a los cambios de configuración.
onSaveInstanceState() se llama antes de destruir la Activity para guardar el estado temporal. Los datos guardados se pasan a onCreate mediante el parámetro savedInstanceState y al método onRestoreInstanceState(), que se llama después de onStart. El Bundle tiene un límite de tamaño — aproximadamente 500 KB, por lo que los grandes volúmenes de datos (por ejemplo, mapas de bits) se guardan mediante ViewModel.
<!-- AndroidManifest.xml — fijación de orientación -->
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
La fijación de la orientación mediante android:configChanges evita la recreación de la Activity, pero se considera un antipatrón si la aplicación debe soportar ambas orientaciones. La recomendación moderna de Google es usar ViewModel junto con onSaveInstanceState para los datos que el usuario introduce en la UI.
Fragment tiene su propio ciclo de vida, similar al de Activity, pero con métodos adicionales: onAttach, onCreate, onCreateView, onViewCreated, onStart, onResume, onPause, onStop, onDestroyView, onDestroy, onDetach. Un Fragment siempre existe dentro de una Activity, y su ciclo de vida está vinculado al ciclo de vida de la Activity contenedora. Si la Activity se destruye, el Fragment la sigue.
La diferencia principal: Fragment gestiona no solo el estado del componente, sino también la jerarquía de View. El método onCreateView devuelve la View raíz del Fragment, y onDestroyView destruye esta jerarquía. Esto permite que el Fragment sobreviva a la recreación de la Activity durante la rotación de pantalla: el Fragment se conserva y su View se recrea en onCreateView.
class ProfileFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
return inflater.inflate(R.layout.fragment_profile, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val avatarImage: ImageView = view.findViewById(R.id.avatar_image)
loadAvatar(avatarImage)
}
}
Comprender la diferencia entre onCreate y onCreateView es críticamente importante: onCreate se llama una vez por vida del Fragment (incluso cuando se recrea la View), mientras que onCreateView se llama cada vez que el Fragment crea o recrea su jerarquía de View. La inicialización de datos se realiza en onCreate, mientras que la vinculación de la UI se realiza en onViewCreated.
LifecycleObserver — un componente de la biblioteca Android Jetpack que permite reaccionar a los cambios del ciclo de vida sin sobrescribir métodos en Activity o Fragment. En lugar de duplicar código en cada método del ciclo de vida, el desarrollador crea una clase separada con anotaciones @OnLifecycleEvent y la pasa a lifecycle.addObserver().
Jetpack también proporciona la interfaz LifecycleOwner, que implementan AppCompatActivity y Fragment. Cualquier objeto que implemente LifecycleOwner puede gestionar suscripciones a LiveData, corrutinas mediante lifecycleScope y WorkManager en relación con el ciclo de vida. Esta es una piedra angular de la arquitectura moderna de Android basada en MVVM y Jetpack.
class MyLocationObserver(private val context: Context) : DefaultLifecycleObserver {
override fun onStart(owner: LifecycleOwner) {
startLocationUpdates()
}
override fun onStop(owner: LifecycleOwner) {
stopLocationUpdates()
}
}
// En Activity:
lifecycle.addObserver(MyLocationObserver(this))
El uso de DefaultLifecycleObserver simplifica las pruebas, reduce la duplicación de código y hace que la lógica del ciclo de vida sea reutilizable entre diferentes pantallas. Este es un reemplazo moderno de la sobrescritura manual de onStart/onStop en cada Activity. En las aplicaciones Android desarrolladas por IT Sectr, aplicamos LifecycleObserver para geolocalización, escaneo Bluetooth y analítica — esto reduce el volumen de código boilerplate en un 30–40%.
Preguntas frecuentes
Si no se llama a super.onCreate() o a cualquier otro método super del ciclo de vida, el sistema lanzará una excepción SuperNotCalledException y la aplicación fallará. Este es un requisito estricto del Android Runtime — cada método debe delegar la ejecución a la clase base, de lo contrario la máquina de estados interna no podrá transicionar al siguiente estado.
La Activity se recrea al rotar la pantalla porque el cambio de orientación es un cambio de configuración del dispositivo. Por defecto, Android destruye la Activity y crea una nueva para cargar recursos alternativos (layout-land, values-land). Para deshabilitar la recreación, se puede añadir el atributo android:configChanges en el manifiesto, pero Google recomienda usar ViewModel para conservar los datos.
Los datos críticos se guardan en onPause(), ya que este es el último método que se garantiza que se llamará antes de que el sistema pueda eliminar la aplicación. Después de onStop y onDestroy, el sistema puede terminar el proceso sin llamar a métodos adicionales. Para borradores y datos intermedios, use SharedPreferences con apply() o Room con corrutinas.
onPause se llama cuando la Activity pierde el foco pero permanece parcialmente visible (por ejemplo, se abre un cuadro de diálogo). onStop se llama cuando la Activity está completamente oculta de la pantalla por otra Activity o al pulsar el botón Inicio. La principal diferencia práctica: onPause es el último punto para guardar datos, onStop es el lugar para liberar listeners y servicios del sistema que no son necesarios en segundo plano.
ViewModel es un componente de Android Jetpack que almacena datos de la UI y sobrevive automáticamente a los cambios de configuración (rotación de pantalla). ViewModel no se destruye cuando se recrea la Activity: vive hasta que el LifecycleOwner (Activity o Fragment) finaliza completamente. Esto resuelve el problema de conservar datos durante la rotación de pantalla sin usar Bundle ni onSaveInstanceState. ViewModel es un elemento obligatorio de la arquitectura MVVM recomendada por Google.
Resumen
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.
Lea también