Flutter Riverpod Tutorial Part 3: Combining Providers
In this tutorial, we will learn how to combine multiple providers to create more complex states and manage dependencies between providers in Riverpod.
Combining Providers
Combining providers allows you to create more complex and interdependent states in your application. Riverpod makes it easy to manage dependencies between different providers. We are going to explore multiple scenarios of combining providers.
Managing User and Post Data
We are going to create an example where we manage both user and post data. We will simulate a scenario where posts are fetched based on the selected user.
Add User Model
Let's create a file user.dart
class User {
final int id;
final String name;
User({required this.id, required this.name});
factory User.fromJson(Map<String, dynamic> json) {
return User(id: json['id'], name: json['name'],);
}
}
Add Post Model
Let's create another file post.dart
class Post {
final int id;
final String title;
final String body;
Post({
required this.id,
required this.title,
required this.body,
});
factory Post.fromJson(Map<String, dynamic> json) {
return Post(
id: json['id'],
title: json['title'],
body: json['body'],
);
}
}
Create our User Provider
I am updating our basic_providers.dart
to include this provider. This is similar to Future Provider from Lesson 2. The only difference is that instead of returning a List of Json we are returning List<User>>
final usersProvider = FutureProvider<List<User>>((ref) async {
final response =
await http.get(Uri.parse('https://jsonplaceholder.typicode.com/users'));
if (response.statusCode == 200) {
List jsonData = json.decode(response.body);
return jsonData.map((user) => User.fromJson(user)).toList();
} else {
throw Exception('Failed to load user');
}
});
Create Selected User Provider
Let's use StateProvider
to manage the selected user:
final selectedUserProvider = StateProvider<User?>((ref)=> null);
Create Post by User Provider
Let's create a postsByUserProvider
that depends on selectedUserProvider
final postsByUserProvider = FutureProvider<List<Post>>((ref) async {
final selectedUser = ref.watch(selectedUserProvider);
if (selectedUser == null) {
return [];
}
final response = await http.get(Uri.parse(
'https://jsonplaceholder.typicode.com/posts?userId=${selectedUser.id}'));
if (response.statusCode == 200) {
final jsonData = json.decode(response.body);
return jsonData.map((post) => Post.fromJson(post)).toList();
} else {
throw Exception('Failed to load posts');
}
});
Use Combined Providers in our
UsersPostPage
Let's create users_posts_page.dart
to display users and posts based on the user:
class UserPostsPage extends ConsumerWidget {
const UserPostsPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final userPosts = ref.watch(postsByUserProvider);
final usersListAsyncValue = ref.watch(usersProvider);
return Scaffold(
appBar: AppBar(
title: const Text('User Posts Page'),
),
body: SizedBox(
width: double.infinity,
child: Column(
children: [
usersListAsyncValue.when(
data: (users) {
// In here we are selecting the users based on drop down
return DropdownButton<User>(
hint: const Text('Select a User'),
items: users
.map((user) => DropdownMenuItem(
value: user, child: Text(user.name)))
.toList(),
onChanged: (user) {
ref.read(selectedUserProvider.notifier).state = user;
});
},
error: (error, stackTrace) => Center(
child: Text('Error: $error'),
),
loading: () => const Center(
child: CircularProgressIndicator(),
),
),
Expanded(
//Only when a user is selected we'll get the posts from that user
child: userPosts.when(
data: (posts) {
return ListView.builder(
itemCount: posts.length,
itemBuilder: (context, index) {
final post = posts[index];
return ListTile(
title: Text(post.title),
subtitle: Text(post.body),
);
});
},
error: (error, stackTrace) => Center(
child: Text('Error: $error'),
),
loading: () => const Center(
child: CircularProgressIndicator(),
),
),
),
],
),
),
);
}
}
Output:
And finally here's the output:
Source Code:
You can find the source code for the app here: riverpod_combining_providers
Subscribe to my newsletter
Read articles from Harish Kunchala directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by