En Flutter las notificaciones suben y los valores bajan

Fabio Santana
4 min readMay 2, 2019

--

En Flutter existen varias formas de comunicar widgets entre sí. En este post veremos dos de ellas: las notificaciones y los valores. Para esto Flutter nos provee de dos tipos de widgets diferentes: NotificationListener y ValueListenableBuilder.

NotificacionListener

Sí lo que necesitamos es comunicar los widgets descendientes de un widget con ese mismo widget, podemos usar el widget NotificationListener.

Este tipo de widget lo podemos usar, por ejemplo, para escuchar el progreso del scroll de un ListView o de un GridView o de cualquier otro widget que tenga un scroll.

¿Hasta que descendiente podemos escuchar las notificaciones?

La comunicación por medio de notificaciones no solo es entre padre e hijo, también puedes enviar notificaciones desde nietos, bisnietos y demás descendientes de un widget.

Las notificaciones suben

Veamos como implementar el uso de notificaciones, primero necesitamos crear un tipo de notificación. Por ejemplo, en este ejemplo enviaremos una notificación con el tiempo actual cuando se presione un botón.

Para crear la notificación solo necesitamos extender de la clase Notification.

Ahora crearemos un widget simple con un botón que al presionarlo envíe una notificación de ese tipo.

Creamos la notificación y llamamos al método dispatch, este método hará que nuestra notificación suba a lo largo del árbol de widgets. Lo puedes ver cómo crear una burbuja y dejarla subir.

Ahora necesitamos escuchar esa burbuja, para eso usamos el widget NotificationListener.

Tenemos un Scaffold y pasamos como body un NotificationListener. El tipo del NotificationListener, en este caso TimeNotification, es importante porque nos permite escuchar solo las notificaciones que nos lleguen de ese tipo y descartar otras notificaciones.

Usamos dos atributos del widget, el child que nos permite seguir creando el árbol de widgets y el atributo onNotification.

Con el onNotification podemos escuchar las notificaciones hechas por la descendencia del child del NotificationListener. Cualquier hijo, nieto, bisnieto… de ese child o ese mismo child que envíe una notificación será recibida en el onNotification.

ValueListenableBuilder

En otras ocasiones lo que necesitamos es la comunicación inversa, enviar datos desde un widget hacia sus hijos, nietos, bisnietos… Esto lo conseguimos con ValueNotifier y el ValueListenableBuilder.

El ValueListenableBuilder puede ser útil para realizar animaciones al poder comunicar, por ejemplo, el progreso de una animación realizada desde un widget a su descendencia.

Los valores bajan

Primero creamos el widget donde queremos recibir el evento.

En este widget podemos comentar varias cosas. Tenemos el ValueListenable que nos permite escuchar los eventos que vengan desde widgets ascendentes. Y el ValueListenableBuilder, es similar al NotificationListener visto anteriormente. Pero en este caso, no pasamos un widget como child proque lo que queremos hacer es construir el widget cuando llegue un evento.

Estos eventos nos los ofrece en este ejemplo el ValueListenable y es el que debemos pasar como valueListenable para que escuche los eventos y nos llame al builder cuando llegue alguno.

Ahora creamos un nuevo widget, este widget será padre del widget anterior y será el que produzca el evento. Añadimos un atributo del tipo ValueNotifier, este atributo nos ayudará a enviar eventos a su descendencia. En ese caso enviaremos eventos del tipo int.

E implementamos el método build.

Cuando creamos el widget anterior CounterText debemos pasarle el _counter que es un ValueNotifier pero que a su vez es un ValueListenable.

CounterText(_counter)

Y por último, añadimos un FloatingActionButton para incrementar el _counter lo que provocará que se lance un evento y lo escuche nuestro CounterText.

onPressed: () => _counter.value++,

ValueListenableBuilder y InheritedWidget

Una mejor solución que pasar el ValueListenable por medio del constructor a la descendencia es usar un InheritedWidget.

Para conseguir esto creamos un InheritedWidget

En este InheritedWidget simplemente añadimos un atributo del tipo ValueListenable<int> y lo pasamos por parámetro en el constructor.

@required this.counter

Además añadimos un método para obtener ese ValueListenable

Vemos ahora como podríamos reescribir el ejemplo anterior usando este CounterListenableProvider. Primero reescribimos el widget que recibirá los eventos.

No necesitamos pasar el ValueListenable por medio de un constructor sino que directamente accedemos al CounterListenableProvider para que nos devuelva su ValueListenable.

Ahora necesitamos crear el CounterListenableProvider.

Recubrimos nuestro anterior body con un CounterListenableProvider y le pasamos el ValueNotifier y el child anterior. Podemos observar ahora que al CounterText() no necesitamos pasarle ningún ValueListenable. Podemos usar el CounterListenableProvider.of(context) en cualquier descendiente del child del CounterListenableProvider. Permitiéndonos una mayor facilidad a la hora de construir el árbol de widgets sin necesidad de estar pasando entre widget el ValueListenable simplemente obteniéndolo del CounterListenableProvider.

Conclusión

En este post hemos aprendido a enviar notificaciones y valores a lo largo del árbol de nuestra UI. Es importante entender que la comunicación desde widgets inferiores a widgets superiores debe ser por medio de Notificaciones y el NotificatonListener. Y para realizar la comunicación contraria desde widgets superiores a widgets inferiores usamos los ValueNotifier y el ValueListenableBuilder. Y para aprovechar al máximo este último sistema podemos usar un InheritedWidget que nos permita compartir un ValueListenable.

--

--