La gestión de estado es un concepto fundamental en el desarrollo de aplicaciones con Flutter. Se refiere a cómo se maneja y se actualiza la información que afecta la interfaz de usuario (UI) de una aplicación. En Flutter, hay varias maneras de gestionar el estado, cada una con sus propias ventajas y desventajas.

¿Qué es el Estado?

En términos simples, el estado es cualquier dato que puede cambiar en una aplicación. Esto incluye:

  • Datos de usuario (como el nombre o la dirección de correo electrónico).
  • Datos de la interfaz de usuario (como el texto de un botón o la visibilidad de un widget).
  • Datos de la aplicación (como la lista de elementos en un carrito de compras).

Tipos de Estado

En Flutter, el estado se puede clasificar en dos tipos principales:

  1. Estado Local: Es el estado que afecta solo a un widget específico. Por ejemplo, el estado de un botón que cambia de color cuando se presiona.
  2. Estado Global: Es el estado que afecta a múltiples widgets en diferentes partes de la aplicación. Por ejemplo, el estado de autenticación de un usuario que afecta a toda la aplicación.

Métodos de Gestión de Estado en Flutter

Flutter ofrece varias maneras de gestionar el estado. A continuación, se describen algunos de los métodos más comunes:

  1. setState

setState es la forma más básica de gestionar el estado en Flutter. Se utiliza principalmente para gestionar el estado local.

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Gestión de Estado con setState'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Has presionado el botón esta cantidad de veces:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Incrementar',
        child: Icon(Icons.add),
      ),
    );
  }
}

Explicación del Código:

  • _counter es una variable de estado que almacena el número de veces que se ha presionado el botón.
  • _incrementCounter es una función que incrementa _counter y llama a setState para notificar a Flutter que el estado ha cambiado.
  • setState actualiza la UI con el nuevo valor de _counter.

  1. InheritedWidget

InheritedWidget es una forma de gestionar el estado global en Flutter. Permite que los widgets hijos accedan al estado sin necesidad de pasarlo explícitamente a través del árbol de widgets.

class Counter extends InheritedWidget {
  final int counter;
  final Widget child;

  Counter({this.counter, this.child}) : super(child: child);

  static Counter of(BuildContext context) {
    return context.dependOnInheritedWidgetOfExactType<Counter>();
  }

  @override
  bool updateShouldNotify(Counter oldWidget) {
    return oldWidget.counter != counter;
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Counter(
      counter: _counter,
      child: Scaffold(
        appBar: AppBar(
          title: Text('Gestión de Estado con InheritedWidget'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'Has presionado el botón esta cantidad de veces:',
              ),
              Text(
                '${Counter.of(context).counter}',
                style: Theme.of(context).textTheme.headline4,
              ),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _incrementCounter,
          tooltip: 'Incrementar',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

Explicación del Código:

  • Counter es un InheritedWidget que almacena el estado _counter.
  • Counter.of(context) permite a los widgets hijos acceder al estado.
  • updateShouldNotify determina si los widgets dependientes deben ser notificados cuando el estado cambia.

  1. Provider

Provider es un paquete popular para la gestión de estado en Flutter. Simplifica el uso de InheritedWidget y proporciona una forma más estructurada de gestionar el estado.

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

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MyApp(),
    ),
  );
}

class Counter with ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<Counter>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Gestión de Estado con Provider'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Has presionado el botón esta cantidad de veces:',
            ),
            Text(
              '${counter.counter}',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: counter.increment,
        tooltip: 'Incrementar',
        child: Icon(Icons.add),
      ),
    );
  }
}

Explicación del Código:

  • ChangeNotifierProvider proporciona una instancia de Counter a la aplicación.
  • Counter es una clase que extiende ChangeNotifier y gestiona el estado _counter.
  • Provider.of<Counter>(context) permite a los widgets acceder al estado y a los métodos de Counter.

Ejercicio Práctico

Ejercicio 1: Contador con setState

Objetivo: Crear una aplicación de contador utilizando setState.

Instrucciones:

  1. Crea un nuevo proyecto de Flutter.
  2. Implementa un contador que incremente el valor cada vez que se presione un botón.
  3. Utiliza setState para actualizar la UI.

Solución:

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Contador con setState'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Has presionado el botón esta cantidad de veces:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Incrementar',
        child: Icon(Icons.add),
      ),
    );
  }
}

Ejercicio 2: Contador con Provider

Objetivo: Crear una aplicación de contador utilizando Provider.

Instrucciones:

  1. Crea un nuevo proyecto de Flutter.
  2. Añade el paquete provider a tu proyecto.
  3. Implementa un contador que incremente el valor cada vez que se presione un botón.
  4. Utiliza Provider para gestionar el estado.

Solución:

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

void main() {
  runApp(
    ChangeNotifierProvider(
      create: (context) => Counter(),
      child: MyApp(),
    ),
  );
}

class Counter with ChangeNotifier {
  int _counter = 0;

  int get counter => _counter;

  void increment() {
    _counter++;
    notifyListeners();
  }
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final counter = Provider.of<Counter>(context);

    return Scaffold(
      appBar: AppBar(
        title: Text('Contador con Provider'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'Has presionado el botón esta cantidad de veces:',
            ),
            Text(
              '${counter.counter}',
              style: Theme.of(context).textTheme.headline4,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: counter.increment,
        tooltip: 'Incrementar',
        child: Icon(Icons.add),
      ),
    );
  }
}

Conclusión

La gestión de estado es un aspecto crucial en el desarrollo de aplicaciones con Flutter. En esta lección, hemos explorado diferentes métodos para gestionar el estado, incluyendo setState, InheritedWidget y Provider. Cada método tiene sus propias ventajas y desventajas, y la elección del método adecuado depende de las necesidades específicas de tu aplicación.

En la próxima lección, profundizaremos en el uso del paquete Provider y exploraremos otros paquetes populares para la gestión de estado, como Riverpod y el patrón Bloc.

Curso de Desarrollo con Flutter

Módulo 1: Introducción a Flutter

Módulo 2: Conceptos Básicos de Programación en Dart

Módulo 3: Widgets en Flutter

Módulo 4: Gestión de Estado

Módulo 5: Navegación y Enrutamiento

Módulo 6: Redes y APIs

Módulo 7: Persistencia y Almacenamiento

Módulo 8: Conceptos Avanzados de Flutter

Módulo 9: Pruebas y Depuración

Módulo 10: Despliegue y Mantenimiento

Módulo 11: Flutter para Web y Escritorio

© Copyright 2024. Todos los derechos reservados