Notas sobre el uso de los operadores de flujo shareIn y stateIn
Los operadores Flow.shareIn y Flow.stateIn convierten los flujos fríos en flujos calientes: pueden transmitir información sobre los flujos fríos aguas arriba a múltiples recolectores. Estos dos operadores se utilizan a menudo para mejorar el rendimiento: para agregar almacenamiento en búfer cuando no hay ningún recopilador disponible, o simplemente como mecanismo de almacenamiento en caché.
En este artículo, lo familiarizaremos con los operadores shareIn y stateIn a través de ejemplos. Aprenderá cómo configurarlos para casos de uso específicos y evitar errores comunes que pueda encontrar.
Continuando con el ejemplo que utilicé en el artículo anterior: publicar actualizaciones de ubicación utilizando un productor de flujo de datos subyacente. Este es un flujo en frío implementado mediante callbackFlow. Cada nuevo recopilador activa el bloque productor de flujo de datos y agrega una nueva devolución de llamada a FusedLocationProviderClient.
Veamos cómo podemos usar shareIn y stateIn para optimizar el flujo de datos de LocationsSource en diferentes casos de uso.
El primer tema que discutiremos es la diferencia entre shareIn y stateIn. El operador shareIn devuelve un SharedFlow, mientras que stateIn devuelve un StateFlow.
StateFlow es una configuración especial de SharedFlow diseñada para optimizar el estado compartido: los últimos elementos enviados se reenvían al nuevo recopilador y los elementos se fusionan utilizando Any.equals. Puede obtener más información sobre esto en la documentación de StateFlow.
La principal diferencia entre los dos es que la interfaz StateFlow le permite acceder sincrónicamente al último valor publicado leyendo la propiedad del valor. No es así como se usa SharedFlow.
Estas API nos brindan mejoras de rendimiento al permitir que el recopilador ****enjoy observe todas las instancias del mismo flujo de datos (en lugar de crear nuevas instancias del mismo flujo de datos bajo demanda).
En el siguiente ejemplo, LocationRepository consumirá el flujo de datos de LocationsSource expuesto por LocationDataSource y utilizará el operador ShareIn para que cada recopilador interesado en la información de ubicación del usuario pueda obtener datos de la misma instancia de flujo de datos. Todos los recopiladores solo crean y comparten una instancia de flujo de datos de LocationsSource:
La estrategia de uso compartido WhileSubscribed se utiliza para cancelar el flujo de datos ascendente cuando no hay ningún recopilador. De esta forma evitamos desperdiciar recursos cuando ningún programa está interesado en las actualizaciones de ubicación.
En el siguiente ejemplo, nuestros requisitos han cambiado. Ahora necesitamos continuar escuchando las actualizaciones de ubicación mientras mostramos las últimas 10 ubicaciones en la pantalla cuando la aplicación regresa del fondo al primer plano:
Establecemos el valor del parámetro de reproducción en 10 para que sea retenido en la memoria Los últimos 10 elementos se envían, mientras que se reenvían cada vez que el recolector observa el flujo de datos. Para mantener el flujo de datos interno siempre activo y enviar actualizaciones de ubicación, utilizamos la política ****heed SharingStarted.Eagerly para que siempre podamos escuchar las actualizaciones incluso si no hay un recopilador.
Nuestras necesidades han cambiado nuevamente, esta vez ya no necesitamos que la aplicación escuche continuamente las actualizaciones de ubicación mientras la aplicación está en segundo plano. Sin embargo, necesitamos almacenar en caché el último elemento enviado para que el usuario pueda ver algunos datos (incluso datos antiguos) en la pantalla al obtener la ubicación actual. En este caso podemos utilizar el operador stateIn.
Flow.stateIn almacenará en caché el último elemento enviado y lo reproducirá para el nuevo recopilador.
Nunca utilices shareIn o stateIn para crear una nueva secuencia cuando regrese una llamada de función. Esto creará un nuevo SharedFlow o StateFlow en cada llamada a función, y permanecerán en la memoria hasta que se eliminen o se recolecten basura cuando no haya más referencias.
Los flujos que requieren parámetros de entrada (como userId) no pueden simplemente usar shareIn o stateIn. Por ejemplo, como puede ver en el código fuente de la aplicación Google I/O para Android, el flujo de datos que recupera eventos de usuario de Firestore es el flujo de datos de Firestore. El flujo de obtención de eventos de usuario de Firestore se implementa como callbackFlow. Dado que toma el ID de usuario como parámetro, no se puede reutilizar simplemente con los operadores shareIn o stateIn.
La forma de optimizar este caso de uso depende de las necesidades de su aplicación:
Los operadores ShareIn y stateIn se pueden usar con flujos en frío para mejorar el rendimiento, que puede usar sin un recopilador. para agregar almacenamiento en búfer o utilizarlos directamente como mecanismo de almacenamiento en caché. Utilícelos con precaución y no cree una nueva instancia de flujo en cada llamada de función, ¡esto puede provocar un desperdicio de recursos y problemas inesperados!