Flutter Riverpod Future Provider – Example

Asynchronous operations are in almost every application that works with a backend. Whether it is GraphQL, Rest, or anything else, you have the same pattern. You start the request, and you wait till the request is finished before you show the data. In Flutter, Riverpod provides us with the FutureProvider. With the FutureProvider, the UI can deal with this synchronously. The FutureProvider will let the Widgets know when the data is ready or when the call failed.

Setup the Project

Before we can start with coding, we are going to add some dependencies to the project. We will need Flutter Hooks, and Hooks Riverpod for the state management.

dependencies:
  flutter:
    sdk: flutter
  flutter_hooks: ^0.18.0
  hooks_riverpod: ^1.0.0-dev.6

Do not forget to install the dependency, running the following command:

flutter pub get

Creating the Repository

First, we are going to create a fake wrapper that retrieves a list of articles. Then, since we want some delay, we are going to return the articles with a delay. For the article, we will use an id and a title.

abstract class ArticleRepository {
  Future<List<Article>> fetchArticles();
}

class FakeArticleRepository implements ArticleRepository {
  @override
  Future<List<Article>> fetchArticles() {
    return Future.delayed(
      Duration(milliseconds: 500),
      () {
        return [
          Article("Article 1", 1),
          Article("Article 2", 2),
          Article("Article 3", 3),
          Article("Article 4", 4),
          Article("Article 5", 5),
          Article("Article 6", 6),
          Article("Article 7", 7)
        ];
      },
    );
  }
}

class Article {
  final String name;
  final int id;

  Article(this.name, this.id);
}

Creating the Future Provider

To access the fake articles, we create a provider of the ArticleRepository. We can access this repository in the FutureProvider. The FutureProvider will return the list of articles that we provide by the FakeArticleRepository.

final articleRepository = Provider<ArticleRepository>(
  (ref) => FakeArticleRepository(),
);

final articles = FutureProvider<List<Article>>((ref) async {
  return ref.watch(articleRepository).fetchArticles();
});

Using the article’s future provider is pretty straightforward. First, we can create a new HookConsumerWidget to use the ref.watch function to retrieve the articles. Then, we can use the when function on the Future that we retrieve with the hook. Based on the current state, we can return the right widget. When the articles are loading, we will return the CircularProgressIndicator. If the articles are ready, we can display them with a simple ListView and ListTile.

class ArticleList extends HookConsumerWidget {
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final article = ref.watch(articles);
    return article.when(
        loading: () => Center(child: const CircularProgressIndicator()),
        error: (err, stack) => Text('Error: $err'),
        data: (articles) {
          return Flexible(
            child: ListView.builder(
                itemCount: articles.length,
                itemBuilder: (BuildContext context, int index) {
                  return ListTile(
                      title: Text(articles[index].name),
                      subtitle: Row(
                        children: [
                          Icon(Icons.thumb_up),
                          Text(" ${articles[index].likes}")
                        ],
                      ));
                }),
          );
        });
  }
}

The full code is available here on Github. If you still have any questions, remarks, or suggestions, do not hesitate to leave a comment or send a message!

Leave a Reply