We shall use Riverpod to get or fetch data from API or endpoint or from the server. For that, we will use get a request from HTTP to fetch API with Riverpod. Moving on the way we will explain some important key properties of Riverpod provider(), ref.watch(), ref.read() and the consumerWidget(). So let’s fetch API with riverpod.

State management with Riverpod

You can see above, first, when the data is loading, the CircularProgressIndicator is showing and then we are displaying data in the listview.

Install Packages

For this tutorial, you need to add two packages in the pubsec.yaml:

flutter_riverpod: ^2.1.3
http: ^0.13.5

Fetch API from the server

Since we are going to get data from the server using the API, we need to create a service class. Create a folder inside the lib folder and name it services. Inside it, create a new class named services.dart.

class ApiService {
  String userUrl = 'https://reqres.in/api/users?page=2';

 Future<List<UserModel>> getUsers() async {
    Response response = await get(Uri.parse(userUrl));
    if (response.statusCode == 200) {
      final List result = jsonDecode(response.body)['data'];
      return result.map((e) => UserModel.fromJson(e)).toList();
    } else {
      throw Exception(response.reasonPhrase);
    }
  }
}
final userProvider=Provider<ApiService>((ref)=>ApiService());

In the file, we created a class ApiService inside where we have the endpoint and a method named getUsers().

Provider

In the last line, you can see we have used Provider. It is the Riverpod provider. In Riverpod, the provider is the entry point of shared data and we have stored the value of the variable userProvider. Since we have created it globally, this instance can be accessed from anywhere through the application.

Provider<T>

Using Provider<T> we create the state that is shared and accessible across the application. This means the UI screens of the application can use them from anywhere. Here T referees to the type. In our application it is ApiService.

Our Provider returns a function and the function takes an ref object. It is like a context in Riverpod.

In simple terms, the Provider returns a shareable object using the given object or class.

Model Class Creation

From the endpoint above, or this link. We are going to create our model class. And from the endpoint, we are just going to take the parameter data.

Create a file named user_model.dart and then create a class.

class UserModel {
  int? id;
  String? email;
  String? firstName;
  String? lastName;
  String? avatar;

  UserModel({this.id, this.email, this.firstName, this.lastName, this.avatar});

  UserModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    email = json['email'];
    firstName = json['first_name'];
    lastName = json['last_name'];
    avatar = json['avatar'];
  }
}

Creating FutureProvider

Create a new dart file named data_provider.dart.

final userDataProvider = FutureProvider<List<UserModel>>((ref) async {
  return ref.watch(userProvider).getUsers();
});

Since we are making a network call that is asynchronous in type, we need to wrap our userProvider using the FutureProvider object. FutureProvider() ensures that the data is updated on the UI screen even if there’s a delay.

You can see, inside FutureProvider we have used ref.watch()to listen to the changes. And if you use ref.read() you may not get the updated value in the UI.

ref.read() / ref.watch()

ref.watch() always watches the data changes and informs the widget about the changes. You can also listen to other providers like userProvider.

ref.read() only read the value once, i.e it is not much reactive enough. If there is change in the data value it won’t read the new value.

Note: If you use ref.read(), you must have to use it inside the build method.

Consumer Widget

Create a new file named home_page.dart.

class HomePage extends ConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, ref) {
    final userData = ref.watch(userDataProvider);
    return Scaffold(
        appBar: AppBar(title: const Text("Riverpod Flutter")),
        body: userData.when(
            data: (userData) {
              List<UserModel> userList = userData.map((e) => e).toList();
              return ListView.builder(
                itemCount: userList.length,
                itemBuilder: (_, index) {
                  return Padding(
                    padding:
                        const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
                    child: Card(
                        color: Theme.of(context).primaryColor,
                        child: ListTile(
                            title: Text(
                              '${userList[index].firstName}  ${userList[index].lastName}',
                              style: const TextStyle(color: Colors.white),
                            ),
                            subtitle: Text(
                              '${userList[index].email}',
                              style: const TextStyle(color: Colors.white),
                            ),
                            leading: CircleAvatar(
                              backgroundImage: NetworkImage(
                                  userList[index].avatar.toString()),
                            ))),
                  );
                });
            },
            error: (error, s) => Text(error.toString()),
            loading: () => const Center(
                  child: CircularProgressIndicator(),
                )));
  

ConsumerWidget here substitutes StatefulWidget. As we are using Riverpod for state management, we use ConsumerWidget which eventually is a StatefulWidget.

Because we have previously used FutureProvider to access the resources from the provider, we can access When() the function of the FutureProvider object from the home page.

ProviderScope

It is the entry point of the Riverpod, so we need to put it in the main.dart file.

class HomePage extends ConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, ref) {
    final userData = ref.watch(userDataProvider);
    return Scaffold(
        appBar: AppBar(title: const Text("Riverpod Flutter")),
        body: userData.when(
            data: (userData) {
              List<UserModel> userList = userData.map((e) => e).toList();
              return ListView.builder(
                itemCount: userList.length,
                itemBuilder: (_, index) {
                  return Padding(
                    padding:
                        const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
                    child: Card(
                        color: Theme.of(context).primaryColor,
                        child: ListTile(
                            title: Text(
                              '${userList[index].firstName}  ${userList[index].lastName}',
                              style: const TextStyle(color: Colors.white),
                            ),
                            subtitle: Text(
                              '${userList[index].email}',
                              style: const TextStyle(color: Colors.white),
                            ),
                            leading: CircleAvatar(
                              backgroundImage: NetworkImage(
                                  userList[index].avatar.toString()),
                            ))),
                  );
                });
            },
            error: (error, s) => Text(error.toString()),
            loading: () => const Center(
                  child: CircularProgressIndicator(),
                )));
}
}
  

Conclusion

In this article, I have explained the Riverpod and the Riverpod working mechanism. You can play around with code as per your need and choice. Try creating a new page. The Riverpod can be very useful for large projects.

I hope this blog post provides you with enough important information on Flutter Riverpod to use the riverpod library and architecture in your upcoming project.

❤ ❤ Thanks for reading this article ❤❤

Also, follow to get updated on exciting articles and projects.

If I got something wrong? Let me know in the comments. I would love to improve.

Let’s get connected

We can be friends. Find on FacebookLinkedinGithubYouTube

BuyMeACoffee, and Instagram.

Contribute: BuyMeACoffee

ContactContact Us

Get the Full code at GitHub

  1. tlover tonet Avatar

    Hey! I know this is kind of off topic but I was wondering if you knew where I could find a captcha plugin for my comment form? I’m using the same blog platform as yours and I’m having trouble finding one? Thanks a lot!

Leave a Reply

Your email address will not be published. Required fields are marked *

Fetch Api with Riverpod