πŸ“± 20 / 100 Days Of Flutter, Kate's edition β€” intro into Riverpod with Providers, Consumers and AsyncValue

πŸ“± 20 / 100 Days Of Flutter, Kate's edition β€” intro into Riverpod with Providers, Consumers and AsyncValue

How are you doing, Flutter community? 🌈
On my side, I'm happy to share with you the 20th update on my Flutter learning challenge!

Finally, I started learning Riverpod state manager which positions itself as "A Reactive Caching and Data-binding Framework". My learning is driven by the amazing Andrea's blog and course. I will share some bits with you here but you can always head to his website and find tons of high-quality Flutter materials.

Providers

My introduction to Riverpod started with providers and consumers. I don't fully understand how it works, but it already makes sense.

Providers are the most important part of a Riverpod application. A provider is an object that encapsulates a piece of state and allows listening to that state.

Riverpod providers reminded me of Redux's reducers but Riverpod implementation is much more powerful as it supports async and streams out of the box.

To start writing providers, I installed the "Flutter Riverpod Snippets" plugin (available for Android Studio and VS Code).

Screenshot 2022-06-12 at 19.05.10.png

Typing "str" or "futu" brings a list of snippet suggestions just like on the screenshot above.

Providers are declared as global variables which is an uncommon practice for the Flutter ecosystem. The official documentation asks us not to worry about it:

Do not be frightened by the global aspect of providers. Providers are fully immutable. Declaring a provider is no different from declaring a function, and providers are testable and maintainable.

I personally like keeping things simple and not worried at all πŸ˜…

Consumers

First and foremost, before reading a provider, we need to obtain a "ref" object. This object is what allows us to interact with providers, be it from a widget or another provider.

The next step is to obtain (consume) values from the providers. To continue React Redux analogy, ConsumerWidget and Consumer are somewhat similar to Redux Connect API. They allow you to obtain that magic ref object and then you can start watching or listening to any providers you need.

class HomeView extends ConsumerWidget {
  const HomeView({Key? key}): super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    // use ref to listen to a provider
    final counter = ref.watch(counterProvider);
    return Text('$counter');
  }
}

The code snippet above is from the official Riverpod documentation (which is very good btw!)

AsyncValue

What I really like about Riverpod is its completeness. Instead of the "doing one thing well" approach, the library covers all popular use cases. For instance, async support is a first-class citizen in Riverpod.

Riverpod has FutureProvider and StreamProvider for async and reactive use cases. Listening to these types of providers returns an AsyncValue – which allows handling of the error/loading states.

class Example extends ConsumerWidget { // Inheriting from ConsumerWidget to get access to ref.
  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final AsyncValue<User> user = ref.watch(userProvider); // Watching FutureProvider or StreamProvider

    // Using AsyncValue utility to handle async
    return user.when(
      loading: () => CircularProgressIndicator(),
      error: (error, stack) => Text('Oops, something unexpected happened'),
      data: (value) => Text('Hello ${user.name}'),
    );
  }
}

The code snippet above is from the official Riverpod documentation.

You can read more about AsyncValue in Andrea's blog.

Widget of the day - CircularProgressIndicator

It's really cool to have beautiful progress indicators available as part of the framework. Flutter comes with CircularProgressIndicator and LinearProgressIndicator. You could see an example use case in the AsyncValue code snippet - if the data is loading, you can simply return CircularProgressIndicator(). If you need something more sophisticated, there are plenty of configuration parameters.

If it's still not enough, there are contrib packages like Shimmer.

Summary

Today I've learned a lot about Riverpod. It's a robust and powerful library that covers many practical use cases like async, caching, autoDispose, etc. Of course, it has a certain learning curve, so I will continue exploring it in the coming days.

If you'd like to connect or collaborate on the Flutter learning process, catch @kalabro on Twitter πŸ‘‹

Β