Contenido del curso
Google Maps SDK
Servicios de Localización
- 7

Kotlin Flows para medir tiempo en Android
12:54 min - 8

Simulación de ubicación GPS en emulador y dispositivo Android
05:48 min - 9

Modelos de localización propios con Clean Architecture
08:36 min - 10

Callbacks de Android convertidos en Flows
14:50 min - 11

Inyección de dependencias para observar localización en Android
06:33 min - 12

LocationTracker con StateFlow para rastreo en Android
Viendo ahora - 13

State Flows para controlar localización y tiempo en Kotlin
10:00 min - 14

Configuración y pruebas de Location Tracker en Android
09:37 min
Integración Maps con Localización
Manejo de permisos
Integración cámara
- 23

Cómo guardar fotos en Android con PhotoHandler
11:59 min - 24

Conversión de Bitmaps a Byte Arrays con Extension Functions
05:58 min - 25

CameraViewModel con Hilt y StateFlow
08:40 min - 26

Configuración de métodos del ViewModel para gestión de cámara
09:40 min - 27

Integración de CameraX con Jetpack Compose en Android
14:23 min - 28

Creación de pantalla de previsualización de fotos con Jetpack Compose
08:44 min - 29

Galería de fotos en marcadores del mapa
11:55 min
Servicios en Android
Transmisiones en Android (Broadcast)
LocationTracker con StateFlow para rastreo en Android
Resumen
Cuando construyes una app que rastrea ubicación, no basta con observar coordenadas: necesitas controlar cuándo se activa, cuándo se pausa y cómo persisten los valores entre vistas. Aquí entra el patrón LocationTracker con StateFlow, una pieza clave para manejar el rastreo de localización en Android de forma eficiente y reactiva.
Qué es la clase LocationTracker y por qué la necesitas
Dentro de la carpeta domain/location creas una clase normal llamada LocationTracker. Su trabajo es orquestar el rastreo: decidir cuándo escuchar la ubicación del dispositivo y cuándo dejar de hacerlo. Para lograrlo, recibe por inyección dos dependencias.
La primera es el LocationObserver que viste en la clase anterior, encargado de emitir las coordenadas. La segunda es un ApplicationScope, que no es un scope cualquiera: se trata de un CoroutineScope declarado para persistir durante toda la vida de la aplicación, ideal para procesos en segundo plano que no deben morir con una pantalla [00:50].
¿Qué es un ApplicationScope en Android? Es un CoroutineScope que vive lo mismo que la app. Lo usas cuando una corrutina debe seguir activa aunque el usuario cambie de pantalla, como en el rastreo de ubicación.
Por qué usar MutableStateFlow en lugar de Flow normal
El corazón de LocationTracker son varios MutableStateFlow. La diferencia con un Flow normal es directa: los StateFlow retienen el último valor emitido, así que cuando una vista se conecta, recibe inmediatamente ese valor sin esperar a una nueva emisión [01:20].
A esto se le llama un hot flow. Puedes manipularlo en tiempo real asignándole el valor que necesites, mientras que los cold flows solo son secuencias que emiten cuando alguien los recolecta.
Qué propiedades expone el LocationTracker
Dentro de la clase declaras cuatro propiedades privadas como MutableStateFlow y las expones públicamente con .asStateFlow() para que nadie de afuera pueda modificarlas directamente.
locationData: arranca vacío y guarda la información de ubicación actual.isTracking: un boolean que indica si la app está rastreando en este momento.isObservingLocation: otro boolean, pero con un propósito distinto aisTracking.elapsedTime: usaDuration.ZEROcomo valor inicial para llevar el tiempo transcurrido del recorrido.
Cada una se expone como un StateFlow inmutable hacia el exterior, manteniendo el control de las mutaciones dentro de la clase.
Cuál es la diferencia entre isTracking e isObservingLocation
Esta distinción es la que más confunde y la que más vale la pena entender. Aunque ambas son banderas booleanas, responden a preguntas diferentes sobre el estado de la app.
¿Cuándo uso isTracking y cuándo isObservingLocation? Usa
isTrackingpara saber si el usuario le dio play o pausa al recorrido. UsaisObservingLocationpara saber si la app cumple las condiciones técnicas (permisos, servicios) para acceder a la ubicación.
En otras palabras, isTracking responde a la intención del usuario, mientras que isObservingLocation responde a si los permisos están habilitados y los componentes del sistema están listos para entregar coordenadas [02:45].
Cómo modificar los valores de los StateFlow con funciones
Para cambiar los valores de estos flows no los expones mutables hacia afuera. En su lugar, defines funciones públicas que acceden a la propiedad .value del MutableStateFlow y la actualizan de forma controlada.
setIsTracking(isTracking: Boolean): recibe un boolean y actualiza el valor de la propiedad interna.startObservingLocation(): poneisObservingLocation.value = truepara activar el rastreo.stopObservingLocation(): poneisObservingLocation.value = falsepara detenerlo.updateLocationData(): reservada para actualizar la ubicación cuando haya fotos disponibles, algo que se conectará con la sección de cámara más adelante.
Este patrón mantiene el principio de encapsulamiento: el estado solo cambia a través de funciones explícitas, lo que hace el código predecible y fácil de testear.
Cómo finalizar un recorrido con finishTracking
La función finishTracking() cierra el ciclo completo del rastreo. Hace cuatro cosas en orden para dejar la app en un estado limpio.
- Llama a
stopObservingLocation()para cortar la escucha de coordenadas. - Ejecuta
setIsTracking(false)para marcar que el recorrido terminó. - Resetea
elapsedTime.valueaDuration.ZEROpara reiniciar el cronómetro. - Vuelve a inicializar
locationData.valuecon unLocationDatavacío.
Un detalle de refactor que aparece en el camino: la propiedad inicialmente llamada location se renombra a locationData con clic secundario y Refactor → Rename, para que el nombre comunique con precisión que se trata del paquete completo de información de ubicación, no solo de coordenadas sueltas.
Por qué este patrón es la base del rastreo en tiempo real
Lo que acabas de construir es el estado central que cualquier ViewModel o pantalla podrá observar. La clase no rastrea por sí misma todavía: define las palancas que se accionarán en la próxima clase, donde estos StateFlow entran en acción combinados con corrutinas y el LocationObserver.
La lógica queda separada en capas claras: LocationObserver produce datos, LocationTracker decide cuándo escuchar y guarda el estado, y la UI solo consume StateFlow expuestos. ¿Has trabajado antes con StateFlow en proyectos propios? Cuéntame en los comentarios cómo lo usaste.