Riverpod ist eine moderne State-Management-Loesung fuer Flutter. Lernen Sie Providers, Code Generation, AsyncValue und fortgeschrittene Muster fuer skalierbare Anwendungen.
Einfuehrung in Flutter State Management¶
Riverpod ist eine moderne State-Management-Loesung fuer Flutter, die viele Einschraenkungen von Provider und InheritedWidget behebt. Es bietet Compile-Time-Sicherheit, bessere Testbarkeit und verbesserte Entwicklererfahrung durch Code Generation und starke Typisierung.
Architektur und Schluesselkonzepte¶
Die Grundlage einer erfolgreichen Flutter-Anwendung mit Riverpod ist das Verstaendnis der Architektur und fundamentaler Konzepte.
Wichtige architektonische Schichten: - Praesentationsschicht - Widgets und UI-Komponenten - Business-Logik - Providers und State Management - Datenschicht - Repositories und Datenquellen - Infrastrukturschicht - Netzwerk, Speicher und Dienste
// Grundlegendes Riverpod-Provider-Beispiel
@riverpod
class Counter extends _$Counter {
@override
int build() => 0;
void increment() => state++;
void decrement() => state--;
}
// Verwendung im Widget
class CounterWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Column(
children: [
Text('Count: $count'),
ElevatedButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: Text('Increment'),
),
],
);
}
}
Providers und Code Generation¶
Riverpod unterstuetzt Code Generation, die Compile-Time-Sicherheit bietet und Boilerplate reduziert. Verwenden Sie die @riverpod-Annotation zur automatischen Provider-Generierung:
@riverpod
Future<List<User>> users(UsersRef ref) async {
final repository = ref.watch(userRepositoryProvider);
return repository.getUsers();
}
@riverpod
class UserNotifier extends _$UserNotifier {
@override
Future<User?> build(String userId) async {
final repository = ref.watch(userRepositoryProvider);
return repository.getUser(userId);
}
Future<void> updateUser(User user) async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(() async {
final repository = ref.watch(userRepositoryProvider);
return repository.updateUser(user);
});
}
}
AsyncValue und Error Handling¶
Riverpod bietet AsyncValue fuer die Behandlung asynchroner Operationen mit integrierten Loading-, Error- und Data-Zustaenden:
class UserProfile extends ConsumerWidget {
final String userId;
const UserProfile({required this.userId});
@override
Widget build(BuildContext context, WidgetRef ref) {
final userAsync = ref.watch(userNotifierProvider(userId));
return userAsync.when(
data: (user) => UserWidget(user: user),
loading: () => const CircularProgressIndicator(),
error: (error, stack) => ErrorWidget(error: error),
);
}
}
Testen mit Riverpod¶
Riverpod erleichtert das Testen durch Provider-Overrides:
void main() {
testWidgets('Counter incrementiert', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [
counterProvider.overrideWith(() => Counter()),
],
child: MyApp(),
),
);
expect(find.text('0'), findsOneWidget);
await tester.tap(find.byType(ElevatedButton));
await tester.pump();
expect(find.text('1'), findsOneWidget);
});
}
Best Practices¶
- Code Generation verwenden - Nutzen Sie
@riverpodfuer Typsicherheit - AsyncValue korrekt behandeln - Immer Loading- und Error-Zustaende behandeln
- Providers fokussiert halten - Ein Provider pro Verantwortlichkeit
- Family fuer parametrisierte Providers verwenden - Parameter an Providers uebergeben
- Mit Overrides testen - Abhaengigkeiten in Tests mocken
Riverpod bietet eine robuste Grundlage fuer Flutter State Management mit hervorragender Entwicklererfahrung und produktionsreifen Mustern.