onStart es un método del ciclo de vida de Android que se llama cuando una Activity o Fragment se vuelve visible para el usuario. En este momento, la pantalla aparece en el display del dispositivo, pero aún no puede interactuar con el usuario: el foco de entrada está ausente hasta que se llama a onResume. El método onStart es ideal para registrar listeners del sistema, conectarse a servicios de geolocalización e iniciar animaciones que deben ejecutarse mientras el componente esté visible en pantalla. Obtén más información sobre el ciclo de vida completo de Activity en el artículo Activity Lifecycle.
Puntos clave
onStart es el segundo método del ciclo de vida de Activity, llamado por el sistema después de onCreate (o después de onRestart al regresar de un estado detenido). En el momento en que se llama a onStart, la Activity o Fragment se vuelve visible en pantalla. El usuario ve la interfaz, pero la pantalla aún no está lista para la interacción: el foco de entrada aparecerá solo después de onResume.
El método onStart forma parte del “período de vida visible” de una Activity: el intervalo entre onStart y onStop. Durante este período, la Activity puede estar parcialmente cubierta por otras ventanas (por ejemplo, una Activity transparente o una ventana de diálogo), pero su UI permanece visible. Esto distingue el período de vida visible del “período de vida en primer plano” (onResume — onPause), cuando la Activity tiene el foco de entrada completo.
Comprender esta jerarquía de tres niveles es fundamental para distribuir correctamente el código. onCreate: inicialización única, onStart: conexión de recursos visibles, onResume: acceso exclusivo a recursos exclusivos. Un desarrollador que confunde estos niveles corre el riesgo de crear fugas de memoria o un comportamiento incorrecto de la aplicación al cambiar entre pantallas.
En Activity, el método onStart se llama cada vez que la pantalla aparece en el display, tanto en el primer inicio (después de onCreate) como al regresar del fondo (después de onRestart). A diferencia de onCreate, onStart puede llamarse múltiples veces durante la vida de una instancia de Activity, por lo que aquí se coloca el código que debe ejecutarse cada vez que aparece la pantalla.
class DashboardActivity : AppCompatActivity() {
private val connectivityReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
val isConnected = ... // Comprobación de ConnectivityManager
binding?.statusIndicator?.setColor(
if (isConnected) Color.GREEN else Color.RED
)
}
}
override fun onStart() {
super.onStart()
registerReceiver(
connectivityReceiver,
IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)
)
SensorManager.getInstance().registerStepCounter()
}
override fun onStop() {
unregisterReceiver(connectivityReceiver)
SensorManager.getInstance().unregisterStepCounter()
super.onStop()
}
}
Regla clave: todos los recursos conectados en onStart deben liberarse en onStop. Esto garantiza que cuando la Activity esté oculta de la pantalla, no consuma batería, no escuche eventos del sistema ni ocupe memoria. Android Studio incluye reglas lint que advierten sobre el registro de un BroadcastReceiver sin la correspondiente cancelación.
onStart en Fragment está estrechamente vinculado al ciclo de vida de la Activity contenedora. El Fragment recibe la llamada onStart después de que la Activity que lo contiene haya recibido onStart. Sin embargo, si el Fragment se agrega en modo diferido (FragmentTransaction.commit() sin addToBackStack), onStart puede llamarse con retraso.
class MapFragment : Fragment() {
private var mapView: MapView? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
mapView = MapView(requireContext())
return mapView!!
}
override fun onStart() {
super.onStart()
mapView?.onStart()
LocationService.connect(requireContext())
}
override fun onStop() {
mapView?.onStop()
LocationService.disconnect()
super.onStop()
}
}
Especificidades de Fragment.onStart: si el Fragment está en un ViewPager con offscreenPageLimit = 1, los fragmentos vecinos también recibirán onStart antes de volverse visibles. Esto puede provocar un registro prematuro de listeners. Para estos casos, use el método setUserVisibleHint() o verifique isVisible dentro de onStart para registrar listeners solo para fragmentos realmente visibles.
La principal diferencia entre onStart y onResume es el nivel de actividad en pantalla. onStart señala que la Activity es visible en pantalla pero no necesariamente está en primer plano. onResume señala que la Activity está en primer plano y tiene el foco de entrada. La diferencia se demuestra con un ejemplo de ventana de diálogo: cuando aparece un Dialog sobre una Activity, la Activity pierde onResume (se llama a onPause) pero permanece visible: no se llama a onStart/onStop.
La tabla comparativa muestra claramente en qué escenarios se llama cada método:
| Escenario | onStart | onResume |
|---|---|---|
| Inicio de la aplicación | Se llama | Se llama |
| Dialog abierto sobre Activity | No se llama | onPause (pierde el foco) |
| Botón de inicio presionado | onStop (oculto) | onPause → onStop |
| Regreso de Recientes | onStart (visible) | onResume (foco) |
| Rotación de pantalla | onCreate → onStart | → onResume |
| Llamada entrante | onStop (oculto) | onPause → onStop |
Esta tabla ayuda al desarrollador a decidir en qué método colocar un código específico. Por ejemplo, si la aplicación debe pausar la reproducción de video durante cualquier superposición de pantalla (incluso un diálogo), el código se coloca en onPause. Si el video debe detenerse solo cuando la pantalla esté completamente oculta, el código se coloca en onStop.
onStart es el lugar óptimo para registrar listeners que solo deben funcionar mientras la Activity sea visible en pantalla. Esto concierne a tres tipos principales de componentes del sistema: BroadcastReceiver para eventos del sistema, LocationListener para geolocalización y SensorListener para sensores del dispositivo.
BroadcastReceiver se registra dinámicamente mediante Context.registerReceiver() en onStart y se cancela en onStop mediante unregisterReceiver(). El registro dinámico es preferible al registro estático (en el manifiesto) porque limita el tiempo de vida del receptor al período de visibilidad de la Activity: la aplicación no se activa con mensajes de broadcast del sistema cuando la Activity está oculta.
private val batteryReceiver = object : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) {
val level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1)
binding?.batteryText?.text = "$level%"
}
}
override fun onStart() {
super.onStart()
registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
}
override fun onStop() {
unregisterReceiver(batteryReceiver)
super.onStop()
}
La geolocalización y los sensores son operaciones que consumen muchos recursos. Solicitar actualizaciones de GPS en onStart y cancelarlas en onStop garantiza que la aplicación no agote la batería cuando la pantalla esté oculta. Para un ajuste fino, use requestLocationUpdates con un intervalo y distancia mínimos, por ejemplo, 10 segundos y 10 metros, lo que proporciona un equilibrio óptimo entre precisión y consumo de energía.
Iniciar animaciones en onStart, en lugar de en onCreate, garantiza que la animación comience cada vez que aparece la pantalla. Si inicia una animación en onCreate, solo funcionará en la primera creación de Activity, no al regresar del fondo. onStart se llama cada vez que la Activity se vuelve visible, lo que lo convierte en el lugar ideal para iniciar animaciones cíclicas y transiciones.
private lateinit var pulseAnimator: ValueAnimator
override fun onStart() {
super.onStart()
pulseAnimator.start()
binding?.loadingIndicator?.animate()?.alpha(1f)?.start()
}
override fun onStop() {
pulseAnimator.cancel()
binding?.loadingIndicator?.animate()?.cancel()
super.onStop()
}
Para animaciones que usan ObjectAnimator o ValueAnimator, es importante llamar a cancel() en onStop. Si la animación continúa ejecutándose después de ocultar la Activity, consume recursos de GPU y CPU innecesariamente, degradando el rendimiento del dispositivo y acelerando el agotamiento de la batería. Android Studio Profiler (gráfico de GPU) permite rastrear animaciones activas y detectar fugas.
La regla de emparejamiento onStart/onStop también se aplica al trabajar con la cámara para vista previa (CameraX). Abrir la cámara en onStart y cerrarla en onStop garantiza que la cámara no esté bloqueada para otras aplicaciones cuando su aplicación no sea visible en pantalla. Violar esta regla es una causa común de reseñas negativas en Google Play.
Preguntas frecuentes
onStart: para listeners que deben funcionar mientras la pantalla esté visible (BroadcastReceiver, LocationListener, SensorListener). onResume: para recursos que requieren acceso exclusivo (cámara, captura de video, reconocimiento de voz). Los listeners de eventos del sistema no requieren acceso exclusivo y pueden funcionar con superposición parcial: se registran en onStart. La cámara solo debe estar activa con el foco completo: se abre en onResume.
onStart siempre se llama si la Activity pasa a un estado visible. El único escenario sin onStart es cuando la Activity se crea y finaliza inmediatamente (por ejemplo, debido a un error en onCreate). En este caso, se llama a onDestroy justo después de onCreate. Pero este es un escenario de emergencia que no debería ocurrir en un código correctamente escrito.
Sí, onStart puede no recibir onResume si otra Activity o una ventana transparente se abre inmediatamente sobre la Activity. Por ejemplo, si se lanza una pantalla de autorización después de onCreate (Activity A → Activity B), en Activity A se llama a onStart, pero no a onResume: recibe inmediatamente onPause → onStop al ser superpuesta por la pantalla B.
onStart puede llamarse múltiples veces durante la vida de una instancia de Activity. Cada vez que la Activity pasa de un estado oculto (onStop) a un estado visible, se llama a onStart. En la práctica, con un uso activo de la aplicación, onStart puede llamarse docenas o cientos de veces por sesión.
Cargar datos en onStart está justificado si los datos deben actualizarse cada vez que aparece la pantalla. Por ejemplo, un feed de noticias o una lista de notificaciones. Sin embargo, la carga debe ser asíncrona, mediante corrutinas con lifecycleScope, para no bloquear el hilo de UI. Para datos que no cambian entre apariciones de pantalla, basta con cargarlos una vez en onCreate.
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