Getx 1 - Variables reactivas y observadores

 Getx 1 - variables reactivas y observadores

He participado y ayudado en bastantes proyectos usando Getx y la mayoría de los programadores no tienen muy claro con Getx que es una variable observable, un observador o un controlador, mezclando todos los conceptos sobre gestión de estados (state management) terminando con un batido confuso.

Getx es un "ecosistema" trata de resolver diversos problemas a los que se enfrenta un programador de Flutter. Por ello es muy fácil perderse al mezclar sus diversas partes. En estos artículos trataré de identificar conceptos y uso de las distintas partes.

En este primer artículo comenzaré por la parte más básica, las variables reactivas y los observadores. 

Seguidor del principio KISS trataré de no agregar más que lo que sea necesario, por ello, aunque hay diversos modelos sólo pretendo exponer el modelo reactivo, ya que es en general el que yo he usado y lo encuentro efectivo, fácil y de poco consumo. Si hay inquietud siempre se puede documentar los diferentes modelos y sus diferencias.

Advertir que todo la funcionalidad de Getx se basa en usar StatelessWidget. Esto es importante por que algunas "decisiones" de diseño son el resultado de esta opción.

¿Controladores, variables, observadores...?

Cuando hablamos de acciones reactivas, es que tu modelo visual reacciona a los diferentes estados de una variable (o variables) de manera "automática" o sea, en general, sin necesidad de tener que llamar a algún "refresh".

Esto no tiene que ver con los controladores. ¿curioso?, pues es cierto, dentro de la gestión de estados de GetX no necesitamos un controlador para poder usar observables.

Por ejemplo, aquí tenemos un página muy simple que usa un contador que es incrementado mediante un botón. Por supuesto, no funciona, ya que no se repinta al cambiar el contador. La variable, por simplificar se ha puesto global, pero puede estar definida en MyApp.

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

var contador = 0;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Reactivo Getx',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Reactivo Getx'),
        ),
        body: Center(
          child: Container(
            child: Text('Contador: $contador'),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () {
            contador++;
          },
        ),
      ),
    );
  }
}

¿Qué hay que hacer en Getx?

Convertir variable a variable observable

Para hacer esto en Getx sólo es necesario asignarle el valor seguida de ".obs". Así convertimos a una variable "reactiva". 

Antes: var contador = 0;
Después: var contador = 0.obs;

Una variable reactiva/observable es un objeto que contiene a nuestra variable:



Antes teníamos una variable "int", ahora, al poner el ".obs" Getx la "recubre" en un objeto reactivo (RxInt en este caso). Por ello para poder recuperar o modificar el valor contenido tendremos que usar el atributo "value" a excepción de lista y mapas de los que ya hablaremos.

Visto esto si a la variable reactiva le asignamos un valor no estaremos cambiando el valor interno sino a ella misma. Para evitar esto es muy conveniente siempre definirlas con "final":

Ahora: final contador = 0.obs;

Cambiar el uso de contador

Cómo hemos comentado ahora necesitamos "value" para acceder al valor interno, modificado nuestro programa:

Antes:
    $contador
    contador++
Ahora:
    ${contador.value}
    contador.value++

Hemos de usar "value" tanto para obtener el valor como para modificarlo.

¿Qué queremos que se actualice?

Es el momento de decidir que parte visual queremos que se modifique al cambiar el valor  de 
"contador", cómo podemos ver con que modifiquemos el Text() que pone el mensaje ya es suficiente, no es necesario cambiar toda la página.

Para decirle a Flutter qué queremos que modifique, envolveremos el/los componentes que queramos en un Obx( () => ) cuyo parámetro es una función que devuelve Widget(), así:

Antes:
    Text('Contador: ${contador.value}');
Ahora:
    Obx( () => Text('Contador: ${contador.value}') );

"Obx" es una función que observará todas variables observables que tenga dentro y si cambia alguna repintará el componente.

Es obvio, aunque no queda de más incidir en que, tiene que existir  al menos una variable observable, dentro de un "Obx".

Podemos poner todos los "Obx" que queramos en la página, incluso podemos poner un "Obx" uno dentro de otro que sabrán que tienen que repintar según que variables sean modificadas.

Así de simple.

Resultado

Por supuesto tenemos que importar la libreria Getx:

En el pubspec.yaml pondremos, por ejemplo get: ^4.3.8

Y en nuestro programa importamos la libreria import 'package:get/get.dart';

El programa queda así

import 'package:flutter/material.dart';
import 'package:get/get.dart';

void main() => runApp(MyApp());

final contador = 0.obs;

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Reactivo Getx',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Reactivo Getx'),
        ),
        body: Center(
          child: Container(
            child: Obx(() => Text('Contador: ${contador.value}')),
          ),
        ),
        floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: () {
            contador.value++;
          },
        ),
      ),
    );
  }
}

Ahora, cuando pulsemos sobre el botón veremos como el texto cambia.

Resumen

Final de la primera parte Getx reactiva. Esto no es todo, en el siguiente hablaremos de Objetos de usuario, Listas y Mapas y de sus peculiaridades y luego del consumo de apis o de elementos future.




Comentarios

  1. Muchas gracias, siempre creí que se usaba un controlador y un GetView para poder usar variables reactivas. ¿Hablaras sobre controladores y la inyección de los mismos? Muchas gracias y buen contenido

    ResponderEliminar

Publicar un comentario

Entradas populares de este blog

Clean Arquitecture: Mi visión en Flutter (2/2), implementando con Getx

Clean Arquitecture: Mi visión en Flutter (1/2).

Getx 2 - variables reactivas - Lista, Mapas, Objetos