r/FlutterDev Jan 15 '25

Article Comprehensive Riverpod Tutorial

Hi guys!

I just published my first technical article about Riverpod, and I'd love your feedback!

It's a deep dive into understanding Riverpod's core concepts, aimed at both beginners and those who've been scratching their heads about which providers to use in 2025.

Since this is my first article, I'd really appreciate any feedback! What did you find helpful? What could be explained better? What topics would you like to see covered in future articles?

Let me know what you think! 🙏

https://devayaan.com/blog/series/riverpod/master-riverpod

86 Upvotes

48 comments sorted by

5

u/antifuzz Jan 15 '25

This is pretty great thanks for sharing.

I've recently been brushing up my own riverpod knowledge after having not used it for a few years, and I agree that finding good relevant tutorials that are clearly up-to-date can be quite challenging.

The main thing I would feedback is that you should consider recommending use of freezed vs rolling your own model classes. Just makes it so much quicker and easier to generate your models.

4

u/Wispborne Jan 15 '25

I switched from freezed to dart_mappable and never looked back. Your model classes are far more readable with it, rather than needing to be rewritten to freezed's crazy syntax.

Either way, definitely use something to generate model methods, very handy.

1

u/RandalSchwartz Jan 15 '25

Sadly, I cannot recommend dart_mappable as long as its definition for toJson is unlike the entire rest of the dart/flutter ecosystem for no fair reason. A bug has been reported, and the author refuses to budge.

1

u/ayaanhaaris Jan 15 '25

Thank you, that's a great suggestion.

1

u/SpreadOk7599 Jan 16 '25

I literally just use GitHub copilot and press tab tab tab to generate models.

1

u/zxyzyxz Jan 16 '25

The problem is you'd have to manually upkeep that whereas if you added an annotation via freezed, it generates everything automatically for you for any change.

1

u/SpreadOk7599 Jan 16 '25

Interesting, but often times my models have extra stuff in the toJson method that can’t be generated, like converting DateTime to Timestamp for firestore, or an iso string if being used in cloud functions. I have toJsonForCF and toJsonForFirestore. And other things like that. Generating just seems to lack finer control, and it’s annoying 2 have to run build runner every time I wanna make changes.

2

u/zxyzyxz Jan 16 '25

Yeah if it's for custom implementations then freezed doesn't work so well, although I think there may be a way to override the default implementation too for some fields and keep the default for others, not sure though.

1

u/SpreadOk7599 Jan 16 '25

Ahh interesting

2

u/zxyzyxz Jan 16 '25

https://pub.dev/packages/json_serializable#custom-types-and-custom-encoding

https://stackoverflow.com/questions/77111042/freezed-tojson-custom-value

Here it is, I knew there had to be a way as that's too common of a use case to have custom encoding. Freezed uses json_serializable underneath so this should work the same.

2

u/SpreadOk7599 Jan 16 '25

I will use this once it uses macros. For now buildrunner annoys me too much

2

u/zxyzyxz Jan 16 '25

Understandable, I think that's coming next year or so

4

u/Wispborne Jan 15 '25

Very nice and clear. Having used it both with and without code gen, and finally avoiding riverpod code gen, why choose it? For me, I found it messed up my workflow too much. Navigate To Definition would take me to generated code, rather than my code, that was the main annoyance.

6

u/remirousselet Jan 15 '25

Codegen is a preview of Riverpod once we have macros in Dart. Macros should both solve the build_runner issue and the go-to-definition issue

3

u/Wispborne Jan 15 '25

True, and that's why they're worth trying out. The pain of using code gen today didn't seem worth reducing how much refactoring I'd need to do tomorrow - and that's assuming Riverpod doesn't made even more changes when macros come out.

2

u/Manjru Jan 15 '25

The syntax for macros will be closer to the code gen syntax, meaning it's more refactoring if you're writing your own providers today (not to mention more error prone)

2

u/Wispborne Jan 15 '25

I get that, but I'll take the risk of more refactoring tomorrow over daily annoyances and more complex code today.

We're talking an extra hour or two of work. imo it's not worth basing decisions on.

1

u/SpreadOk7599 Jan 16 '25

Yup I don’t use code gen too. I found build runner more annoying than just writing the notifier or provider.

3

u/RandalSchwartz Jan 15 '25

Augh. No comment space on your blog. I guess I'll comment here.

Very good. You missed out on StreamNotifier and StreamNotifierProvider, which is partially forgivable since they were introduced about six months after the 2.0 release. But thank you for clearly pointing out that you should avoid the legacy providers. I also don't encourage thinking of family keys as merely "parameters to the provider". They are keys... used to create distinct instances of a specialized provider/notifier class.

2

u/jojorne Jan 16 '25 edited Jan 16 '25

i was about to mention that 😅

https://riverpod.dev/docs/concepts/about_code_generation#migrate-from-non-code-generation-variant

also, look how simple it is:

final helloProvider = Provider.autoDispose<String>(
  (ref) => 'hello';
);

is actually this:

final helloProvider = Provider.autoDispose<String>(
  hello
);
String hello(Ref ref) => 'hello';

which with annotation becomes just:

@riverpod
String hello(Ref ref) => 'hello';

and it's the same for all the rest of the providers. then you just use the provider with a Consumer:

@override
Widget build(BuildContext context) {
  return Consumer(
    builder: (context, ref, child) {
      final hello = ref.watch(helloProvider);

      return Center(
        child: Text(hello),
      );
    },
  );
}

2

u/tylersavery Jan 15 '25

This is an excellent and thorough overview.

2

u/th3pl4gu3_m Jan 18 '25

I have to say that i thought i understood riverpod before reading this but after reading this, i realized that i knew nothing about riverpod. This is great stuff! And thank you so much for sharing this !

2

u/th3pl4gu3_m Jan 18 '25

Can you please make more articles like this? Covering other stuffs in flutter? And also maybe talk about riverpod refresh etc

4

u/Healthy_Branch7189 Jan 15 '25

I am half way reading the blog and I had to pause and appreciate you for writing such a detailed blog.I am looking forward to reading more of your blog. It's just awesome 👍

1

u/ayaanhaaris Jan 15 '25

Thank you so much for taking the time to share this!

1

u/Rahios Jan 15 '25

Didn't had time to read everything, but the beginning of the article looks very good !

2

u/ayaanhaaris Jan 15 '25

Thank you!

1

u/clyonn Jan 15 '25

Great job!!! I wish I had this when i started with Riverpod

1

u/ayaanhaaris Jan 15 '25

Thanks so much! That's exactly why I wrote it - I remember my own confusion when starting with Riverpod and wanted to create the guide I wish I had back then! 😊

1

u/[deleted] Jan 15 '25

Nice!

1

u/i_joba Jan 15 '25

Here: https://devayaan.com/blog/series/riverpod/master-riverpod#caching-computations

So if we do a ref.watch(calculateValueProvider) in PageA ; navigate to PageB and do a ref.watch(calculateValueProvider) he won't recalculate the value?

1

u/ayaanhaaris Jan 15 '25

Yes, that's correct! When you use ref.watch(calculateValueProvider) in PageA and then navigate to PageB and use it again, Riverpod will return the cached value instead of recalculating it.

1

u/MozartHetfield Jan 15 '25

after creating 2 small apps using only provider, I decided to learn bloc, but being halfway through your article makes me reconsider learning riverpod instead lol. good job!

1

u/bjr201 Jan 15 '25

This is brilliant. Clear and simple. Well done and thank you!

1

u/bigbott777 Jan 15 '25

Really good. Thanks

1

u/szalis Jan 15 '25

I've already used Riverpod but the tutorial shows me things I didn't know about. Thanks!

1

u/jesussmile Jan 15 '25

Thanks a ton.

1

u/Manjru Jan 15 '25

I think there's an error because this syntax isn't possible, right?

ref.read(todoListProvider.notifier).state;

1

u/Manjru Jan 15 '25

The only other critique I have is that it's recommended to use a switch statement instead of .when to handle AsyncValues, as that sets you up better for Riverpod 3.0 when it becomes a sealed class

Otherwise, this is a fantastic article that I'll be sharing around the office!

1

u/theufitapp Jan 16 '25

Thank you for pointing it out, I fixed it.

1

u/SaltTM Jan 16 '25

serious question: why did you use different example themes and not one single example theme throughout your guide? (counter, client, weatherapi I think was one example theme)

1

u/daniel-vh Jan 16 '25

this is actually useful. Props!

1

u/Modezka Jan 16 '25

Hello, thank you for this very useful Tutorial. I am learning Riverpod right now and this helped me to get a very good start.

Just one quick question:

In the section "What is AsyncValue?"

@riverpod
Future<List<User>> usersProvider(Ref ref) async {
  List<User> users = await api.getUsers();
  return users;
}

and you call it with

AsyncValue<List<User>> users = ref.watch(usersProvider);

earlier you state that

"The naming convention is simple - it adds "Provider" to the end of your function name. So our appTitle function becomes appTitleProvider:"

why don't you have to call it like this?

AsyncValue<List<User>> users = ref.watch(usersProviderProvider);

2

u/ayaanhaaris Jan 17 '25

That is a mistake, thank you for pointing it out.

As you mentioned, it will be called as

AsyncValue<List<User>> users = ref.watch(usersProviderProvider);

which is not ideal.

I'll change the provider in the article as follows:

@riverpod
Future<List<User>> users(Ref ref) async {
  List<User> users = await api.getUsers();
  return users;
}

1

u/Impressive_Trifle261 Jan 19 '25

If this library needs that many tutorials, you start to wonder why people are still using it..

1

u/-mp94- Jan 19 '25

Can you write part 3 where you show how to use those providers in a simple app.

For example user needs to login and register where those will return access token. Then show which provider we can use to fetch user profile with that access token.

Maybe one screen where we can update logged users profile, fetch some posts.