El paquet provider
és una solució popular per a la gestió de l'estat en aplicacions Flutter. És fàcil d'utilitzar, escalable i es basa en els principis de la programació reactiva. En aquest tema, aprendrem com utilitzar el paquet provider
per gestionar l'estat de la nostra aplicació.
Continguts
Introducció al Paquet Provider
El paquet provider
és una implementació de la Inversió de Dependències (DI) i la Injecció de Dependències (DI) per a Flutter. Permet compartir dades entre diferents parts de l'aplicació de manera eficient i reactiva.
Avantatges del Paquet Provider
- Simplicitat: És fàcil d'entendre i implementar.
- Escalabilitat: Pot gestionar estats simples i complexos.
- Reactivitat: Actualitza automàticament els widgets quan les dades canvien.
Instal·lació del Paquet Provider
Per començar a utilitzar el paquet provider
, primer hem d'afegir-lo al nostre projecte Flutter.
- Obre el fitxer
pubspec.yaml
. - Afegeix la dependència del
provider
:
- Executa
flutter pub get
per instal·lar el paquet.
Creació d'un Model de Dades
Abans de poder utilitzar el provider
, necessitem un model de dades. Crearem una classe simple que representi el nostre model.
class CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } }
Explicació del Codi
CounterModel
: És la nostra classe de model que conté l'estat.ChangeNotifier
: És una classe de Flutter que proporciona la funcionalitat de notificació de canvis._count
: És una variable privada que emmagatzema el valor del comptador.increment
: És un mètode que incrementa el valor del comptador i notifica els oients dels canvis.
Proveïdor de Dades
Ara que tenim el nostre model de dades, necessitem proporcionar-lo a la nostra aplicació. Utilitzarem el widget ChangeNotifierProvider
per fer-ho.
void main() { runApp( ChangeNotifierProvider( create: (context) => CounterModel(), child: MyApp(), ), ); }
Explicació del Codi
ChangeNotifierProvider
: Proporciona una instància deCounterModel
a l'arbre de widgets.create
: És una funció que crea una nova instància deCounterModel
.MyApp
: És el widget principal de la nostra aplicació.
Consum de Dades
Per consumir les dades proporcionades pel provider
, utilitzarem el widget Consumer
.
class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Provider Example'), ), body: Center( child: Consumer<CounterModel>( builder: (context, counter, child) { return Text( 'Count: ${counter.count}', style: TextStyle(fontSize: 24), ); }, ), ), floatingActionButton: FloatingActionButton( onPressed: () { Provider.of<CounterModel>(context, listen: false).increment(); }, child: Icon(Icons.add), ), ); } }
Explicació del Codi
Consumer<CounterModel>
: Consumeix les dades delCounterModel
.builder
: És una funció que es crida cada vegada que les dades canvien.Provider.of<CounterModel>(context, listen: false)
: Obté una instància deCounterModel
sense escoltar els canvis.
Exemple Pràctic
A continuació, es mostra un exemple complet que combina tots els passos anteriors.
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp( ChangeNotifierProvider( create: (context) => CounterModel(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Provider Example'), ), body: Center( child: Consumer<CounterModel>( builder: (context, counter, child) { return Text( 'Count: ${counter.count}', style: TextStyle(fontSize: 24), ); }, ), ), floatingActionButton: FloatingActionButton( onPressed: () { Provider.of<CounterModel>(context, listen: false).increment(); }, child: Icon(Icons.add), ), ); } } class CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } }
Exercicis Pràctics
- Exercici 1: Crea una aplicació que utilitzi el
provider
per gestionar una llista de tasques. Implementa funcionalitats per afegir i eliminar tasques. - Exercici 2: Modifica l'exemple pràctic per afegir un botó que decrementi el valor del comptador.
Solucions
Solució Exercici 1:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp( ChangeNotifierProvider( create: (context) => TaskModel(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: TaskPage(), ); } } class TaskPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Task Manager'), ), body: Column( children: [ Expanded( child: Consumer<TaskModel>( builder: (context, taskModel, child) { return ListView.builder( itemCount: taskModel.tasks.length, itemBuilder: (context, index) { return ListTile( title: Text(taskModel.tasks[index]), trailing: IconButton( icon: Icon(Icons.delete), onPressed: () { taskModel.removeTask(index); }, ), ); }, ); }, ), ), Padding( padding: const EdgeInsets.all(8.0), child: TextField( onSubmitted: (value) { Provider.of<TaskModel>(context, listen: false).addTask(value); }, decoration: InputDecoration( labelText: 'Add Task', border: OutlineInputBorder(), ), ), ), ], ), ); } } class TaskModel with ChangeNotifier { List<String> _tasks = []; List<String> get tasks => _tasks; void addTask(String task) { _tasks.add(task); notifyListeners(); } void removeTask(int index) { _tasks.removeAt(index); notifyListeners(); } }
Solució Exercici 2:
import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; void main() { runApp( ChangeNotifierProvider( create: (context) => CounterModel(), child: MyApp(), ), ); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: MyHomePage(), ); } } class MyHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Provider Example'), ), body: Center( child: Consumer<CounterModel>( builder: (context, counter, child) { return Text( 'Count: ${counter.count}', style: TextStyle(fontSize: 24), ); }, ), ), floatingActionButton: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ FloatingActionButton( onPressed: () { Provider.of<CounterModel>(context, listen: false).increment(); }, child: Icon(Icons.add), ), SizedBox(height: 10), FloatingActionButton( onPressed: () { Provider.of<CounterModel>(context, listen: false).decrement(); }, child: Icon(Icons.remove), ), ], ), ); } } class CounterModel with ChangeNotifier { int _count = 0; int get count => _count; void increment() { _count++; notifyListeners(); } void decrement() { _count--; notifyListeners(); } }
Conclusió
En aquest tema, hem après com utilitzar el paquet provider
per gestionar l'estat en aplicacions Flutter. Hem vist com instal·lar el paquet, crear un model de dades, proporcionar-lo a l'aplicació i consumir-lo en els widgets. També hem treballat amb exemples pràctics i exercicis per reforçar els conceptes apresos. Amb aquesta base, estàs preparat per gestionar estats més complexos en les teves aplicacions Flutter.
Curs de Desenvolupament Flutter
Mòdul 1: Introducció a Flutter
- Què és Flutter?
- Configuració de l'Entorn de Desenvolupament
- Comprensió de l'Arquitectura de Flutter
- Creació de la Teva Primera Aplicació Flutter
Mòdul 2: Conceptes Bàsics de Programació en Dart
- Introducció a Dart
- Variables i Tipus de Dades
- Sentències de Flux de Control
- Funcions i Mètodes
- Programació Orientada a Objectes en Dart
Mòdul 3: Widgets de Flutter
- Introducció als Widgets
- Widgets Stateless vs Stateful
- Widgets Bàsics
- Widgets de Disseny
- Widgets d'Entrada i Formulari
Mòdul 4: Gestió de l'Estat
Mòdul 5: Navegació i Enrutament
- Introducció a la Navegació
- Navegació Bàsica
- Rutes Nomenades
- Passar Dades Entre Pantalles
- Deep Linking
Mòdul 6: Xarxes i APIs
- Obtenir Dades d'Internet
- Analitzar Dades JSON
- Gestió d'Errors de Xarxa
- Ús d'APIs REST
- Integració de GraphQL
Mòdul 7: Persistència i Emmagatzematge
- Introducció a la Persistència
- Preferències Compartides
- Emmagatzematge de Fitxers
- Base de Dades SQLite
- Ús de Hive per a l'Emmagatzematge Local
Mòdul 8: Conceptes Avançats de Flutter
- Animacions en Flutter
- Pintura Personalitzada i Canvas
- Canals de Plataforma
- Isolates i Concurrència
- Optimització del Rendiment
Mòdul 9: Proves i Depuració
- Introducció a les Proves
- Proves Unitàries
- Proves de Widgets
- Proves d'Integració
- Tècniques de Depuració
Mòdul 10: Desplegament i Manteniment
- Preparació per al Llançament
- Construcció per a iOS
- Construcció per a Android
- Integració i Desplegament Continu (CI/CD)
- Manteniment i Actualització de la Teva Aplicació