Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

464
Vistas
¿Cómo .collectAsState() de un StateFlow usando repeatOnLifecycle() en un @Composable?

Estoy tratando de seguir las pautas oficiales para migrar de LiveData a Flow/StateFlow con Compose, según estos artículos:

Una forma más segura de recopilar flujos de las IU de Android

Migración de LiveData a Kotlin's Flow

Estoy tratando de seguir lo que se recomienda en el primer artículo, en la colección Safe Flow en la sección Jetpack Compose cerca del final.

En Compose, los efectos secundarios deben realizarse en un entorno controlado. Para eso, usa LaunchedEffect para crear una rutina que siga el ciclo de vida del componible. En su bloque, puede llamar a suspender Lifecycle.repeatOnLifecycle si lo necesita para volver a iniciar un bloque de código cuando el ciclo de vida del host se encuentra en un estado determinado.

Me las arreglé para usar .flowWithLifecycle() de esta manera para asegurarme de que el flujo no se emite cuando la aplicación pasa a segundo plano:

 @Composable fun MyScreen() { val lifecycleOwner = LocalLifecycleOwner.current val someState = remember(viewModel.someFlow, lifecycleOwner) { viewModel.someFlow .flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED) .stateIn( scope = viewModel.viewModelScope, started = SharingStarted.WhileSubscribed(5000), initialValue = null ) }.collectAsState() }

Encuentro esto muy "boilerplatey" - debe haber algo mejor. Me gustaría tener StateFlow en ViewModel, en lugar de Flow que se convierte a StateFLow en @Composable, y usar .repeatOnLifeCycle() , para poder usar múltiples .collectAsState() con menos repeticiones.

Cuando trato de usar .collectAsState() dentro de una corrutina (LaunchedEffect), obviamente obtengo un error acerca de que .collectAsState() debe llamarse desde el contexto de la función @Composable.

¿Cómo puedo lograr una funcionalidad similar a la de .collectAsState(), pero dentro de .repeatOnLifecycle()? ¿Tengo que usar .collect() en StateFlow y luego ajustar el valor con State? ¿No hay nada con menos repetitivo que eso?

over 4 years ago · Santiago Trujillo
2 Respuestas
Responde la pregunta

0

Después de leer algunos artículos más, incluyendo

Cosas que debe saber sobre los operadores shareIn y stateIn de Flow

Historia de diseño de la API repeatOnLifecycle

Cada vez estoy más convencido de usar .flowWithLifecycle() de esta manera en lugar de repeatOnLifecycle() + ProduceState(). Acabo de hacer esta función de extensión para aliviar el repetitivo al recopilar un flujo como estado de un @Composable:

 @Composable fun <T> Flow<T>.flowWithLifecycleStateInAndCollectAsState( scope: CoroutineScope, initial: T? = null, context: CoroutineContext = EmptyCoroutineContext, ): State<T?> { val lifecycleOwner = LocalLifecycleOwner.current return remember(this, lifecycleOwner) { this .flowWithLifecycle(lifecycleOwner.lifecycle, Lifecycle.State.STARTED) .stateIn( scope = scope, started = SharingStarted.WhileSubscribed(5000), initialValue = initial ) }.collectAsState(context) }

Esto se usaría así en un @Composable:

 @Composable fun SomeScreen() { //... val someState = viewModel.someFlow .flowWithLifecycleStateInAndCollectAsState( scope = viewModel.viewModelScope //or the composable's scope ) //... }

Marcaré esto como una solución aceptada en caso de que ayude a alguien más, a menos que alguien me informe de una mejor manera en los próximos días.

over 4 years ago · Santiago Trujillo Denunciar

0

Sobre la base de la respuesta de OP, puede ser un poco más liviano al no pasar por StateFlow internamente, si no le importa el comportamiento de WhileSubscribed(5000) .

 @Composable fun <T> Flow<T>.toStateWhenStarted(initialValue: T): State<T> { val lifecycleOwner = LocalLifecycleOwner.current return produceState(initialValue = initialValue, this, lifecycleOwner) { lifecycleOwner.lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { collect { value = it } } } }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda