La misma consulta de Room, observarTodos(), recolectada directamente (izquierda) y convertida en StateFlow con stateIn en el ViewModel (derecha). Añade colectores y modifica la tabla.
Flow no ejecuta ninguna consulta: los dos contadores están a 0.La UI recolecta el Flow del DAO
value)@Query("SELECT * FROM libros ORDER BY year DESC") fun observarTodos(): Flow<List<Libro>> // Cada colector de la UI: repository.observarLibros().collect { libros -> … }
La UI recolecta el StateFlow del ViewModel
value)upstream: parado
val uiState: StateFlow<LibrosUiState> =
repository.observarLibros()
.map<List<Libro>, LibrosUiState> { LibrosUiState.Exito(it) }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
initialValue = LibrosUiState.Cargando
)
El mismo stateIn con las tres estrategias de SharingStarted del Anexo B2-A1. La pantalla recolecta con collectAsStateWithLifecycle(): deja de recolectar en segundo plano y desaparece un instante al girar el dispositivo. El reloj avanza en tiempo real.
Un Snackbar «añadido a favoritos» enviado de tres formas. La pantalla lo recoge con LaunchedEffect(Unit) { viewModel.eventos.collect { … } }, como en T2 §6: al girar el dispositivo, la composición se destruye y se vuelve a crear, y el colector desaparece durante un instante.