Provider — ein Paket zur Zustandsverwaltung für Flutter, erstellt von Remi Rousselet im Jahr 2019 als Wrapper über InheritedWidget. Provider löst das Problem der Datenweitergabe nach unten im Widget-Baum ohne Props Drilling: Jedes Widget kann über context.read<T>() oder context.watch<T>() auf den Zustand zugreifen. Laut pub.dev ist Provider der beliebteste Zustandsmanager für Flutter mit über 25.000 Likes.
Wichtige Punkte
Provider — ein Paket zur Zustandsverwaltung und Abhängigkeitsinjektion in Flutter, aufgebaut auf InheritedWidget. Provider stellt ein Objekt (Zustand, Dienst, Repository) im Widget-Baum bereit und baut die UI bei Datenänderungen automatisch neu auf. Im Gegensatz zur direkten Verwendung von InheritedWidget entfernt Provider den gesamten Boilerplate-Code: Es muss keine Unterklasse von InheritedWidget geschrieben, keine statische of()-Methode eingerichtet und keine Verschachtelung verwaltet werden.
Provider ist die offiziell von Google empfohlene Methode zur Zustandsverwaltung in Flutter (Flutter Team, 2019–2023). Das Paket ist Teil des Flutter Ecosystems und wird vom Flutter-Team gewartet. Bei seiner Veröffentlichung wurde Provider als Ersatz für globale Variablen und InheritedWidget vorgeschlagen: Jedes Objekt ist von überall aus zugänglich, ohne durch den Konstruktor übergeben werden zu müssen.
Laut der Flutter Community Survey 2025 wird Provider in 72 % der Flutter-Anwendungen verwendet. Die Hauptgründe für seine Beliebtheit sind: minimale Einstiegshürde, integrierte ChangeNotifier-Unterstützung, Kompatibilität mit anderen Architekturen (MVVM, BLoC) und keine externen Abhängigkeiten.
ChangeNotifier — eine integrierte Flutter-Klasse, die das Listener-Muster implementiert. ChangeNotifier benachrichtigt Abonnenten über Änderungen durch Aufruf von notifyListeners(). Im Kontext von Provider ist ChangeNotifier die Hauptklasse für den Zustand: Es wird eine Klasse erstellt, die ChangeNotifier mit Feldern und Methoden erweitert, die nach Datenänderungen notifyListeners() aufrufen.
class CounterProvider extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners();
}
void reset() {
_count = 0;
notifyListeners();
}
}Regeln für notifyListeners: Nach vollständiger Änderung der Daten aufrufen — nicht in der Mitte einer Methode, sondern am Ende. Wenn eine Methode mehrere Änderungen durchführt, rufen Sie notifyListeners() einmal nach allen Änderungen auf, nicht nach jeder einzelnen. Dies verhindert mehrere Neuzeichnungen in einem logischen Schritt. Für Batch-Updates verwenden Sie notifyListeners zusammen mit setState-ähnlichen Mustern.
Alternativen zu ChangeNotifier: ValueNotifier — für einen einzelnen Wert (gut für Grundelemente), StateNotifier — aus dem Paket state_notifier (selten allein verwendet). Die meisten Provider-Lösungen verwenden ChangeNotifier aufgrund seiner integrierten Unterstützung und Einfachheit.
Consumer — ein Widget, das ChangeNotifier abonniert und bei jedem Aufruf von notifyListeners() neu aufbaut. Consumer akzeptiert eine Builder-Funktion mit drei Parametern: context, model, child. Child — ein Widget, das nicht vom Modell abhängt und von Consumer nicht neu aufgebaut wird. Dies ist eine Optimierung: Wenn Consumer ein statisches Widget (Symbol, Text ohne Daten) enthält, wird es über child übergeben und nicht neu erstellt.
Consumer<CounterProvider>(
builder: (context, provider, child) => Column(
children: [
child!, // wird nicht neu aufgebaut
Text('${provider.count}'),
ElevatedButton(
onPressed: () => provider.increment(),
child: Icon(Icons.add),
),
],
),
child: Text('Zähler:'),
)context.watch — eine Erweiterungsmethode von BuildContext zum Abonnieren eines Providers. Gibt das Modell zurück und abonniert das aktuelle Widget auf dessen Änderungen. context.read — Zugriff ohne Abonnement (für onPressed-Handler, initState und dispose). context.select — Abonnement auf ein bestimmtes Feld des Modells, ohne bei Änderung anderer Felder neu aufzubauen. Select ist die leistungsfähigste Option für komplexe Modelle mit 10+ Feldern.
Wann Consumer, watch oder select verwenden: Consumer — wenn ein Child-Widget zur Optimierung benötigt wird. watch — in der build-Methode zum einfachen Lesen. select — wenn das Modell mehrere Felder hat, das Widget aber nur von einem abhängt. Provider kündigt das Abonnement automatisch bei Zerstörung des Widgets und verhindert so Speicherlecks.
MultiProvider — ein Widget zum Registrieren mehrerer Provider ohne Verschachtelung. Anstatt eines Baums mit 5 Ebenen von Provider → Provider → Provider akzeptiert MultiProvider eine Liste von Anbietern. Jeder nachfolgende Provider kann die vorherigen über den Konstruktor verwenden. MultiProvider ist die Standardmethode zur Organisation der Stammebene einer Anwendung.
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => CartProvider()),
ChangeNotifierProvider(create: (_) => AuthProvider()),
ProxyProvider<AuthProvider, OrderProvider>(
update: (_, auth, __) => OrderProvider(auth.userId),
),
],
child: MaterialApp(home: HomePage()),
)ProxyProvider — ein Provider, der von einem anderen Provider abhängt. ProxyProvider bezieht Werte von anderen Providers und übergibt sie an sein Objekt. Beispielsweise hängt OrderProvider von AuthProvider ab (benötigt userId). Wenn sich AuthProvider ändert, erstellt ProxyProvider automatisch OrderProvider mit der neuen userId neu. ChangeNotifierProxyProvider — die Version von ProxyProvider für ChangeNotifier.
StreamProvider und FutureProvider: StreamProvider abonniert einen Stream (Firebase, WebSocket) und aktualisiert Consumer bei jedem neuen Ereignis. FutureProvider — für asynchrone Initialisierung: Führt einen Future aus, zeigt Laden an und übergibt dann das Ergebnis an die Widgets. Beide lösen häufige Aufgaben ohne manuelle Abonnementverwaltung.
Provider wird getestet, indem das Widget in einen MultiProvider mit Testwerten eingewickelt wird. Für den Test wird keine echte API oder Datenbank benötigt — der Provider wird durch ein gemocktes Objekt ersetzt. Das Paket provider bietet ProviderScope zur Isolierung von Tests — jeder Test erstellt unabhängig seinen eigenen Provider-Baum.
import 'package:flutter_test/flutter_test.dart';
void main() {
testWidgets('Counter increments on button tap',
(tester) async {
await tester.pumpWidget(
ChangeNotifierProvider(
create: (_) => CounterProvider(),
child: CounterScreen(),
),
);
await tester.tap(find.byKey(Key('increment')));
await tester.pump();
expect(find.text('1'), findsOneWidget);
},
);
}MockProvider: Zum Testen von Widgets mit einem Provider, der von einer API abhängt, erstellen Sie eine Stub-Unterklasse oder verwenden Sie mockito / mocktail. Provider benötigt keine speziellen Mock-Tools — jedes Objekt, das ChangeNotifier erweitert, kann über create übergeben werden, ohne den echten Dienst aufzurufen. Programmieren Sie Providers über Schnittstellen (abstrakte Klasse) für einfachen Austausch.
Die Leistung von Provider basiert auf InheritedWidget: Wenn sich ein Provider ändert, werden alle über context.watch oder Consumer abonnierten Widgets neu aufgebaut. Um unnötiges Neuzeichnen zu vermeiden, verwenden Sie context.select (Abonnement auf ein bestimmtes Feld), Consumer mit dem child-Parameter und const für statische Widgets. Provider baut keine Zweige neu auf, die nicht auf Änderungen abonniert sind.
| Methode | Abonnement | Neuaufbau | Verwendung |
|---|---|---|---|
| context.watch | Vollständiges Modell | Jede Änderung | Einfache Widgets |
| Consumer | Vollständiges Modell | Jede Änderung | Mit child-Optimierung |
| context.select | Bestimmtes Feld | Nur bei Feldänderung | Komplexe Modelle |
| context.read | Nein | Nie | Ereignisbehandler |
Einschränkungen: Provider unterstützt keine Isolierung von Geschäftslogik auf Ereignisebene (wie BLoC). Alle Änderungen erfolgen durch direkte Aufrufe von ChangeNotifier-Methoden, was zu unkontrollierten Änderungsketten führen kann. Für komplexe Szenarien (mehrere asynchrone Operationen, komplexe Validierung) ist Provider gegenüber BLoC und Riverpod unterlegen.
Migration von Provider: Provider kann leicht mit anderen Paketen kombiniert werden. Für die Migration zu Riverpod verwenden Sie ChangeNotifierProvider.adaptive — einen Adapter, der die Verwendung vorhandener ChangeNotifier mit Riverpod ohne Umschreiben ermöglicht. Für BLoC — BlocProvider kann innerhalb eines Provider-Baums platziert werden, wodurch ChangeNotifier schrittweise durch Bloc ersetzt wird.
Häufig gestellte Fragen
Provider — ein Wrapper über InheritedWidget zur Abhängigkeitsinjektion mit ChangeNotifier. BLoC — ein Architekturmuster mit Event + Stream zur Logikisolierung. Provider ist einfacher zu erlernen, BLoC strukturiert Code strenger. Provider eignet sich für kleine Anwendungen und UI-Zustand, BLoC für komplexe Geschäftslogik. Laut Flutter Community 2025 werden beide oft zusammen im selben Projekt verwendet.
ChangeNotifierProvider — eine Art von Provider für ChangeNotifier-Instanzen. Erstellt das Objekt über create, stellt es Nachkommen zur Verfügung und baut Consumer bei Aufruf von notifyListeners neu auf. ChangeNotifierProvider ruft automatisch dispose auf ChangeNotifier auf, wenn es aus dem Baum entfernt wird. Es gibt drei Erstellungsmethoden: ChangeNotifierProvider.value (für ein vorhandenes Objekt), ChangeNotifierProvider (für verzögerte Erstellung) und ChangeNotifierProvider.create (für explizite verzögerte Erstellung).
Verwenden Sie context.select anstelle von context.watch — das Widget baut nur neu auf, wenn sich das ausgewählte Feld ändert. Teilen Sie große ChangeNotifier in mehrere kleine auf (ein Modell — eine Verantwortung). Verwenden Sie Consumer child für statische Teile. Für Listen verwenden Sie ListView.builder mit Schlüsseln. Provider DevTools (Flutter Inspector) zeigt, welche Widgets neu aufgebaut werden und warum.
Ja. Provider (ohne ChangeNotifier) — zum Injizieren unveränderlicher Objekte (Repository, API-Client, Konfiguration). ValueListenableProvider — für ValueNotifier. StreamProvider — für Stream (Firebase, WebSocket). FutureProvider — für Future (Laden der Konfiguration beim Start). ProxyProvider — für Providers, die von anderen Providers abhängen. ChangeNotifier wird nur für veränderlichen Zustand mit UI-Aktualisierung benötigt.
ProviderNotFoundException — eine Laufzeitausnahme, die auftritt, wenn versucht wird, einen Provider abzurufen, der nicht weiter oben im Widget-Baum deklariert wurde. Häufige Ursachen: Provider ist weiter unten deklariert als das Widget, das ihn lesen möchte; Provider ist in einer Route deklariert und wird in einer anderen gelesen; Tippfehler im Typ. Lösung: Setzen Sie den Provider weiter oben im Baum ein oder verwenden Sie MultiProvider auf MaterialApp-Ebene für globale Abhängigkeiten.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch