Jetpack Compose III: Flujo de datos y eventos

Facundo Rodríguez Arceri
3 min readNov 4, 2019

--

En esta tercera parte de la serie de artículos sobre Jetpack Compose veremos cómo estructurar/diseñar nuestras funciones @Composable para simplificar la arquitectura y seguir ciertas reglas que nos harán la vida más fácil a la hora de mantener el código de nuestra interfaz gráfica.

Si recién estás empezando por este artículo entonces te recomiendo que le pegues un vistazo a los anteriores, empezando por el primero:

Single source of truth / Fuente única de verdad

Es un principio de desarrollo de software, el cual tiene como objetivo que el estado de la aplicación, o los datos de nuestro modelo sean modificados siempre desde un único lugar y, en caso de que algún otro componente dependa de este estado, lo haga a través de referencias al mismo pero sin modificarlo. De esta forma podemos asegurarnos que no habrá problemas como race-conditions y demás, ya que no existirá más de un componente modificando los datos de la aplicación, evitando la redundancia de los datos (por estar almacenados en varios lugares) y minimizando la posibilidad de llegar a estados inconsistentes.

La forma en la que Jetpack Compose propone respetar este principio es teniendo un flujo de datos que cumpla con dos reglas:

  • Los datos tienen un flujo top-down.
  • Los eventos tienen un flujo bottom-up.

Flujo de datos: top-down

Lo que esta regla quiere decir es que las funciones @Composable deben recibir como parámetro aquellos objetos de los que dependen para poder dibujarse correctamente.

Como estas funciones serán invocadas por otros @Composable que las contengan, decimos que los datos vienen de arriba hacia abajo.

Se debe evitar a toda costa el uso de variables globales para acceder al estado que una @Composable necesita: si se requieren datos adicionales, entonces estos deberían ser parámetro de entrada de la función.

Ejemplo: la siguiente función @Composable de nuestro ejemplo habitual recibe como parámetro el objeto Player que va a representar, ya que necesita acceder a su nombre y número. Nótese que no se reciben datos adicionales, como ser la posición del jugador en el listado, ya que no será necesario. Tampoco se accede a ningún otro valor por fuera de los que se reciben como parámetro.

Flujo de eventos: bottom-up

Esta regla se respeta haciendo que las modificaciones o acciones que se realizan sobre un @Composable no dependan de esta misma función, sino de aquella que la invocó. De esta forma se consiguen dos cosas:

  • En caso de tener que modificar el dato del que depende la función, no será esta quien lo haga. Al delegarlo, podemos mantener el principio de single source of truth.
  • Se favorece a la reutilización del Composable: Si se necesita usar el mismo elemento gráfico en otra parte de la aplicación pero manejando la acción de otra manera, entonces se podrá hacer fácilmente ya que la acción está definida por quien llama al @Composable y no por él mismo.

¿Cómo se implementa esto? De la misma forma que la regla anterior: con parámetros. Se agregarán lambdas que deben manejar los cambios de evento que se esperan sobre el @Composable.

Si volvemos al ejemplo del listado de jugadores, y necesitamos implementar un click listener sobre cada fila, debemos hacer lo siguiente:

Y ahora cuando la PlayerList invoque a PlayerRow, hará lo siguiente:

Conclusión

Siempre que aparecen nuevas herramientas para desarrollar partes de nuestras apps nacen los mismos interrogantes: ¿cómo debo estructurar mi código? ¿existe alguna arquitectura recomendada?. En este caso, el equipo de Compose se encargó, desde el primer momento, en brindarnos estas dos reglas para simplificar el diseño y beneficiar la reutilización de nuestras @Composable.

Otros links de interés

--

--