Cuando usamos StateFlows en Android podemos tomar los datos emitidos por ese StateFlow con collectState desde nuestro View en Jetpack Compose, de esta manera podemos usar el estado para pintar lo que queramos en la pantalla:
@Composable
fun MyComposableScreen(myViewModel: MyViewModel = hiltViewModel(),
) { val myState = myViewModel.myStateFlow.collectAsState()
// Aquí podemos usar myState como nos de la gana, por ejemplo supongamos que myViewModel descarga un usuario cuando se inicia y luego guarda ese usuario en myState, pues podríamos pintar el correo del usuario
Text(
text = myState.value.user.email
)
}
Por lo general esto no es un problema porque en estos días nuestro internet es rápido, pero supongamos que sucede una o ambas de estas cosas:
- Un usuario tiene internet super lento.
- En lugar de descargar un usuario, descargamos un montón de datos, por ejemplo una lista de datos.
Ahora supongamos que este usuario abre la pantalla MyComposableScreen, pero como su internet es lento y son muchos datos se desespera y cierra la pantalla o la app completa, collectAsState() no tiene un mecanismo para saber el estado del ciclo de vida de nuestra Activity y por lo tanto pueden surgir problemas, comúnmente uno de estos dos:
- Un memory leak, esto significa que cuando los datos terminen de cargarse collectAsState() los va a tomar y quedarán en memoria, si el usuario entra y sale muchas veces de la pantalla la app podría tomar mucha memoria del dispositivo.
- Que cuando se finalmente los datos se descarguen se haga collect del estado y trate de pintarlo, pero como la Activity ya no existe la app truene (crashee) al no haber un contexto.
Para solucionar esto en lugar de collectAsState() deberíamos usar collectAsStateWithLifecycle(), su función es la misma pero el segundo está al tanto del estado en el que se encuentra el ciclo de vida de nuestra Activity, así, empieza a intentar hacer collect en Activity onStart() y termina de hacerlo en onStop()

Para usar collectAsStateWithLifecycle() lo único que debemos hacer es agregar esta dependencia en el build.gradle
...
dependencies {
implementation "androidx.lifecycle:lifecycle-runtime-compose:2.6.0" // La versión puede cambiar
}
Luego, en tu Composable, simplemente cambia collectAsState() por collectAsStateWithLifecycle():
@Composable
fun MyComposableScreen(myViewModel: MyViewModel = hiltViewModel(),
) { val myState = myViewModel.myStateFlow.collectAsStateWithLifecycle()
// Aquí podemos usar myState como nos de la gana, por ejemplo supongamos que myViewModel descarga un usuario cuando se inicia y luego guarda ese usuario en myState, pues podríamos pintar el correo del usuario
Text(
text = myState.value.user.email
)
}