🧩 Que é Provider? #
Provider é unha das solucións máis recomendadas para xestionar estado en Flutter de forma eficiente, modular e reactiva. Está construída sobre InheritedWidget, pero ofrece unha API moito máis sinxela e potente.
✅ Vantaxes de usar Provider #
- 🔀 Separación clara entre lóxica de estado e interface de usuario.
- 🌍 Estado global compartido entre diferentes widgets da árbore.
- 🔁 Reactivo: só se reconstrúen os widgets que consumen datos modificados.
- 🧠 Fácil de aprender: ideal para comezar en Flutter.
- ⚡ Eficiente: grazas a
InheritedWidget, reconstrúe só o necesario. - 🔧 Flexible: funciona con calquera tipo de obxecto (non só
ChangeNotifier). - 🤝 Gran comunidade e documentación.
- 🚀 Bo rendemento: evita reconstrucións innecesarias.
📌 Características #
Provider é amplamente utilizado na comunidade Flutter, especialmente para aplicacións pequenas e medianas. A súa popularidade débese á súa:
- Simplicidade
- Flexibilidade
- Eficiencia
Está construído sobre os InheritedWidget de Flutter, pero encapsulado dunha forma moderna e accesible.
🤔 É a mellor opción? #
Depende das túas necesidades. Non hai unha única “mellor” solución, pero Provider é un excelente punto de partida e cobre a gran maioría de casos.
⚖️ Provider vs setState #
setState é a forma máis básica de xestión de estado en Flutter. Ideal para widgets que teñen estado local e simple. Por exemplo:
📌 Se o estado só afecta ao propio widget ou a fillos inmediatos, usa
setState.
En cambio, Provider é máis axeitado para:
- Compartir estado entre diferentes pantallas ou widgets
- Xestionar lóxica de negocio por separado da UI
- Aplicacións máis complexas ou de maior tamaño
🧪 Exemplo con setState #
📌 Cando usar setState ou Provider #
| Situción | Usa setState ✅ | Usa Provider 📦 |
|---|---|---|
| Estado local ao widget | ✅ | |
| Cambio que afecta só ao widget ou a fillos directos | ✅ | |
| Lóxica sinxela | ✅ | |
| Estado compartido entre múltiples widgets non relacionados | 📦 | |
| Separación entre UI e lóxica de negocio | 📦 | |
| Aplicación mediana ou grande | 📦 | |
| Precisas reconstruír só partes concretas da UI eficientemente | 📦 |
⚙️ Instalación #
Engade provider ao teu pubspec.yaml:
dependencies:
flutter:
sdk: flutter
provider: ^6.0.5 # Usa a versión máis recente dispoñible
⚠️ Importante: Despois de gardar o ficheiro, executa
flutter pub getno teu terminal para descargar o paquete.
🧬 Estrutura básica de Provider #
Para empregar Provider nunha app Flutter, seguimos estes pasos fundamentais:
Modelo de estado: Crear unha clase que estenda
ChangeNotifier.
Esta clase conterá os datos e métodos que queres compartir.Proporcionar o estado á árbore de widgets mediante
ChangeNotifierProvider.
Isto adoita facerse preto do widget raíz (por exemplo directamente nomain()).Ler, modificar, escoitar e acceder ao estado usando métodos como
context.watch<T>(),context.read<T>()ou o widgetConsumer<T>().
🧰 Métodos para acceder ao estado #
| Método | Uso recomendado | Exemplo |
|---|---|---|
context.watch<T>() | 🔄 Escoita os cambios do provedor e reconstrúe o widget automaticamente cando o estado cambia. Úsase dentro do método build(). | final contador = context.watch<Contador>(); |
context.read<T>() | 🔹 Lée o estado unha unica vez sen escoitar cambios. Ideal para chamadas únicas, fóra do método build(), por exemplo, nun onPressed. | context.read<Contador>().incrementar(); |
Consumer<T>(...) | 🎯 Widget que reconstrúe só a parte necesaria da UI cando o estado cambia. | Consumer<Contador>(builder: (_, c, __) => Text('${c.valor}')) |
Provider.of<T>(context) | ⚠️ Obsoleto en moitos casos. Non se recomenda. | – |
💡 Nota:
Consumeré útil cando queres optimizar o rendemento e evitar que todo o widget se reconstrúa. Ideal para widgets anidados con partes independentes.
🧪 Exemplo: contador con Provider #
1️⃣ Definir o estado: Modelo #
import 'package:flutter/material.dart';
class Contador extends ChangeNotifier {
int _valor = 0;
int get valor => _valor;
void incrementar() {
_valor++;
notifyListeners(); // notifica os widgets que escoitan
}
}
2️⃣ Proporcionar o estado #
import 'package:flutter/material.dart';
import 'package:provider/provider.dart'; // Importa o paquete provider
// Asegúrate de ter a clase Contador definida como no paso 1
void main() {
runApp(
ChangeNotifierProvider(
create: (contexto) => Contador(),
child: AplicacionContador(),
),
);
}
3️⃣ Modificar o estado. Interface de usuario que escoita #
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
// Asegúrate de ter a clase Contador definida
class AplicacionContador extends StatelessWidget {
@override
Widget build(BuildContext contexto) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Contador con Provider')),
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextoContador(),
BotonIncrementar(),
],
),
),
);
}
}
class TextoContador extends StatelessWidget {
@override
Widget build(BuildContext contexto) {
final contador = context.watch<Contador>();
return Text('Valor actual: ${contador.valor}', style: TextStyle(fontSize: 24));
}
}
class BotonIncrementar extends StatelessWidget {
@override
Widget build(BuildContext contexto) {
final contador = context.read<Contador>();
return ElevatedButton(
onPressed: contador.incrementar,
child: Text('Incrementar'),
);
}
}