State Managementintermediate
Riverpod AsyncNotifier
Modern Riverpod 2.x AsyncNotifier pattern for async state management with codegen-ready syntax.
#riverpod#state-management#async
dart
| 1 | import 'package:riverpod_annotation/riverpod_annotation.dart'; |
| 2 | |
| 3 | part 'user_provider.g.dart'; |
| 4 | |
| 5 | @riverpod |
| 6 | class UserNotifier extends _$UserNotifier { |
| 7 | @override |
| 8 | Future<User> build(String userId) async { |
| 9 | return _fetchUser(userId); |
| 10 | } |
| 11 | |
| 12 | Future<void> refresh() async { |
| 13 | state = const AsyncLoading(); |
| 14 | state = await AsyncValue.guard(() => _fetchUser(ref.read(userIdProvider))); |
| 15 | } |
| 16 | |
| 17 | Future<void> updateName(String newName) async { |
| 18 | final current = state.valueOrNull; |
| 19 | if (current == null) return; |
| 20 | |
| 21 | state = const AsyncLoading(); |
| 22 | state = await AsyncValue.guard(() async { |
| 23 | final updated = await ref.read(userRepositoryProvider).updateName(current.id, newName); |
| 24 | return updated; |
| 25 | }); |
| 26 | } |
| 27 | |
| 28 | Future<User> _fetchUser(String id) { |
| 29 | return ref.read(userRepositoryProvider).getUser(id); |
| 30 | } |
| 31 | } |
| 32 | |
| 33 | // Simple provider |
| 34 | @riverpod |
| 35 | Future<List<Post>> userPosts(Ref ref, String userId) async { |
| 36 | final user = await ref.watch(userNotifierProvider(userId).future); |
| 37 | return ref.read(postRepositoryProvider).getPostsByUser(user.id); |
| 38 | } |
| 39 | |
| 40 | // Usage |
| 41 | class UserPage extends ConsumerWidget { |
| 42 | const UserPage({super.key, required this.userId}); |
| 43 | final String userId; |
| 44 | |
| 45 | @override |
| 46 | Widget build(BuildContext context, WidgetRef ref) { |
| 47 | final userAsync = ref.watch(userNotifierProvider(userId)); |
| 48 | return userAsync.when( |
| 49 | data: (user) => Text(user.name), |
| 50 | loading: () => const CircularProgressIndicator(), |
| 51 | error: (err, _) => Text('Error: $err'), |
| 52 | ); |
| 53 | } |
| 54 | } |