Cómo gestionar el estado en Flutter con Provider

Introducción
La gestión del estado implica el seguimiento de los cambios de estado en toda la aplicación.
El providerpaquete es una solución para las necesidades de gestión estatal.
En este artículo, aprenderá cómo aplicar provideruna aplicación Flutter de muestra para administrar el estado de la información de la cuenta de usuario.
Prerrequisitos
Para completar este tutorial, necesitarás:
- Para descargar e instalar Flutter .
- Para descargar e instalar Android Studio o Visual Studio Code .
- Se recomienda instalar complementos para su editor de código:
FlutteryDartcomplementos instalados para Android Studio.Flutterextensión instalada para Visual Studio Code.
- La familiaridad con la navegación y las rutas será beneficiosa, pero no obligatoria.
- La familiaridad con el estado del formulario también será beneficiosa, pero no es obligatoria.
Este tutorial fue verificado con Flutter v2.0.6, Android SDK v31.0.2 y Android Studio v4.1.
Entendiendo el problema
Imagina una situación en la que quieres crear una aplicación que personaliza algunas de sus pantallas con algunos datos del usuario, como su nombre. Los métodos normales para pasar datos entre pantallas se convertirían rápidamente en un lío de devoluciones de llamadas, datos no utilizados y widgets reconstruidos innecesariamente. Con una biblioteca de interfaz como React, este es un problema común llamado prop boring .
Si quisiéramos pasar datos desde cualquiera de esos widgets, entonces tendríamos que aumentar aún más cada widget intermedio con más devoluciones de llamadas sin usar. Para la mayoría de las funciones pequeñas, esto puede hacer que no valga la pena el esfuerzo.
Afortunadamente para nosotros, el providerpaquete nos permite almacenar nuestros datos en un widget que está más arriba, como donde sea que inicialicemos nuestro MaterialApp, luego acceder a él y cambiarlo directamente desde los sub-widgets, independientemente de la anidación y sin reconstruir todo lo demás.
Paso 1: Configuración del proyecto
Una vez que haya configurado su entorno para Flutter, puede ejecutar lo siguiente para crear una nueva aplicación:
- flutter create flutter_provider_example
Navegue hasta el nuevo directorio del proyecto:
- cd flutter_provider_example
El uso flutter createproducirá una aplicación de demostración que mostrará la cantidad de veces que se hace clic en un botón.
Paso 2: Agregar el providercomplemento
A continuación, necesitaremos agregar el providercomplemento dentro de nuestro pubspec.yaml:
archivo pubspec.yaml
dependencies: flutter: sdk: flutter provider: ^3.1.0
Luego, guarde los cambios en su archivo.
Nota: Si está utilizando VS Code, puede considerar usar la extensión Pubspec Assist para agregar dependencias rápidamente.
Ahora podemos continuar y ejecutar esto en el simulador o dispositivo iOS o Android de su elección.
Paso 3: Andamiaje del proyecto
Necesitaremos dos pantallas, nuestro enrutador y una barra de navegación. Estamos configurando una página para mostrar los datos de nuestra cuenta y otra para actualizarla con el estado que se almacena, cambia y transmite desde nuestro enrutador.
Abra main.dartsu editor de código y modifique las siguientes líneas de código:
lib/main.dart
import 'package:flutter/material.dart';import 'package:provider/provider.dart';import './screens/account.dart';import './screens/settings.dart';void main() { runApp(MyApp());}class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Provider Demo', home: MyHomePage(), ); }}class MyHomePage extends StatefulWidget { @override _MyHomePageState createState() = _MyHomePageState();}class _MyHomePageState extends StateMyHomePage { @override Widget build(BuildContext context) { return MaterialApp(home: AccountScreen(), routes: { 'account_screen': (context) = AccountScreen(), 'settings_screen': (context) = SettingsScreen(), }); }}
Crea un navbar.dartarchivo y ábrelo con tu editor de código:
lib/navbar.dart
import 'package:flutter/material.dart';import './screens/account.dart';import './screens/settings.dart';class Navbar extends StatelessWidget { @override Widget build(BuildContext context) { return Container( color: Colors.blue, child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: Widget[ TextButton( onPressed: () = Navigator.pushReplacementNamed(context, AccountScreen.id), child: Icon(Icons.account_circle, color: Colors.white) ), TextButton( onPressed: () = Navigator.pushReplacementNamed(context, SettingsScreen.id), child: Icon(Icons.settings, color: Colors.white) ), ], ), ); }}
En el libdirectorio, crea un nuevo screenssubdirectorio:
- mkdir lib/screens
En este subdirectorio, crea un settings.dartarchivo. Este se utilizará para crear el estado de nuestro formulario, configurar un mapa para almacenar nuestras entradas y agregar un botón de envío que utilizaremos más adelante:
lib/pantallas/configuraciones.dart
import 'package:flutter/material.dart';import 'package:provider/provider.dart';import '../main.dart';import '../navbar.dart';class SettingsScreen extends StatelessWidget { static const String id = 'settings_screen'; final formKey = GlobalKeyFormState(); final Map data = {'name': String, 'email': String, 'age': int}; @override Widget build(BuildContext context) { return Scaffold( bottomNavigationBar: Navbar(), appBar: AppBar(title: Text('Change Account Details')), body: Center( child: Container( padding: EdgeInsets.symmetric(vertical: 20, horizontal: 30), child: Form( key: formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: Widget[ TextFormField( decoration: InputDecoration(labelText: 'Name'), onSaved: (input) = data['name'] = input, ), TextFormField( decoration: InputDecoration(labelText: 'Email'), onSaved: (input) = data['email'] = input, ), TextFormField( decoration: InputDecoration(labelText: 'Age'), onSaved: (input) = data['age'] = input, ), TextButton( onPressed: () = formKey.currentState.save(), child: Text('Submit'), style: TextButton.styleFrom( primary: Colors.white, backgroundColor: Colors.blue, ), ) ] ), ), ), ), ); }}
También en este subdirectorio, crea un account.dartarchivo que se utilizará para mostrar la información de la cuenta:
lib/pantallas/cuenta.dart
import 'package:flutter/material.dart';import 'package:provider/provider.dart';import '../main.dart';import '../navbar.dart';class AccountScreen extends StatelessWidget { static const String id = 'account_screen'; @override Widget build(BuildContext context) { return Scaffold( bottomNavigationBar: Navbar(), appBar: AppBar( title: Text('Account Details'), ), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: Widget[ Text('Name: '), Text('Email: '), Text('Age: '), ], ), ), ); }}
Compila tu código y ejecútalo en un emulador:
En este punto, tienes una aplicación con una pantalla de Cuenta y una pantalla de Configuración.
Paso 4 — UsoProvider
Para configurar un testamento providerserá necesario envolver nuestro MaterialAppen un Providercon el tipo de nuestros datos.
Vuelve a consultarlo main.darty ábrelo en tu editor de código. Para este tutorial, el tipo de datos es Map. Por último, debemos configurarlo createpara que luego usemos nuestro contexty data:
lib/main.dart
// ...class _MyHomePageState extends StateMyHomePage { Map data = { 'name': 'Sammy Shark', 'email': 'example@example.com', 'age': 42 }; @override Widget build(BuildContext context) { return ProviderMap( create: (context) = data, child: MaterialApp(home: AccountScreen(), routes: { 'account_screen': (context) = AccountScreen(), 'settings_screen': (context) = SettingsScreen(), }), ); }}
El datamapa ahora está disponible en todas las demás pantallas y widgets que main.dartllaman e importan el providerpaquete.
Todo lo que le pasamos a nuestro Providercreador ahora está disponible en Provider.ofMap(context). Tenga en cuenta que el tipo que pasa debe coincidir con el tipo de datos que nuestro creador Providerespera.
Nota: Si estás usando VS Code, quizás quieras considerar usar fragmentos , ya que probablemente accederás providera mucho:
dardo.json
"Provider": { "prefix": "provider", "body": [ "Provider.of$1(context).$2" ]}
Vuelve a consultarlo account.darty ábrelo en tu editor de código. Agrega las siguientes líneas de código:
lib/pantallas/cuenta.dart
// ...body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: Widget[ Text('Name: ' + Provider.ofMap(context)['name'].toString()), Text('Email: ' + Provider.ofMap(context)['email'].toString()), Text('Age: ' + Provider.ofMap(context)['age'].toString()), ]), ),)// ...
Compila tu código y ejecútalo en un emulador:
En este punto, tienes una aplicación con datos de usuario codificados que se muestran en la pantalla Cuenta.
Paso 5 — UsoChangeNotifier
Usar Providereste método parece muy descendente, ¿qué pasa si queremos pasar datos y modificar nuestro mapa? El método Providerpor sí solo no es suficiente para eso. Primero, necesitamos descomponer nuestros datos en su propia clase que extienda ChangeNotifier. Providerno funcionará con eso, por lo que necesitamos cambiarlo a ChangeNotifierProvidery pasar una instancia de nuestra Dataclase en su lugar.
Ahora estamos pasando una clase completa y no solo una única variable, esto significa que podemos comenzar a crear métodos que pueden manipular nuestros datos, que también estarán disponibles para todo lo que acceda Provider.
Después de cambiar cualquiera de nuestros datos globales que queramos usar notifyListeners, esto reconstruirá todos los widgets que dependen de él.
Revisalo main.darty ábrelo en tu editor de código:
lib/main.dart
// ...class _MyHomePageState extends StateMyHomePage { @override Widget build(BuildContext context) { return ChangeNotifierProviderData( create: (context) = Data(), child: MaterialApp(home: AccountScreen(), routes: { 'account_screen': (context) = AccountScreen(), 'settings_screen': (context) = SettingsScreen(), }), ); }}class Data extends ChangeNotifier { Map data = { 'name': 'Sammy Shark', 'email': 'example@example.com', 'age': 42 }; void updateAccount(input) { data = input; notifyListeners(); }}
Dado que cambiamos nuestro Providertipo, necesitamos actualizar nuestras llamadas a él. Vuelve a visitarlo account.darty ábrelo en tu editor de código:
lib/pantallas/cuenta.dart
// ...body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: Widget[ Text('Name: ' + Provider.ofData(context).data['name'].toString()), Text('Email: ' + Provider.ofData(context).data['email'].toString()), Text('Age: ' + Provider.ofData(context).data['age'].toString()), ]), ),)// ...
Para pasar datos, necesitaremos acceder al Providermétodo que se pasó en la Dataclase. Vuelva a consultarlo settings.darty ábralo en su editor de código:
lib/pantallas/configuraciones.dart
TextButton( onPressed: () { formKey.currentState.save(); Provider.ofData(context, listen: false).updateAccount(data); formKey.currentState.reset(); },)
Compila tu código y ejecútalo en un emulador:
En este punto, tienes una aplicación que admite la actualización de la información del usuario en la pantalla de Configuración y la visualización de los cambios en la pantalla de Cuenta.
Conclusión
En este artículo, aprendió cómo aplicar provideruna aplicación Flutter de muestra para administrar el estado de la información de la cuenta de usuario.
Si desea obtener más información sobre Flutter, consulte nuestra página de temas de Flutter para ver ejercicios y proyectos de programación.

Deja una respuesta