Slide 1

Slide 1 text

Riverpod Introduction Jhin Lee Full-Stack Developer Unity

Slide 2

Slide 2 text

Speaker - Jhin Lee ● Full-Stack Developer @Unity ○ Golang, JS/TS, React.js(Next.js), GCP ● Full-Stack Developer @ConsiderBeyond ○ Firebase + Flutter ○ https://www.considerbeyond.com ● LinkedIn: https://www.linkedin.com/in/leehack

Slide 3

Slide 3 text

Agenda ● What is Riverpod? ● What is (Riverpod’s)Provider? ● Code generation ● Different kinds of providers ○ Function Provider ○ Class Provider ● How to read a provider ● How does provider works? ● How to install ● Todo App demo - Let’s code!

Slide 4

Slide 4 text

What is Riverpod? ● Author: Remi Rousselet ○ Author of provider, freezed, and more. ● riverpod (an anagram of provider) is a reactive caching framework for Flutter/Dart. ● riverpod is a complete rewrite of the provider package to make improvements. ● Catch errors at compile-time rather than at runtime.

Slide 5

Slide 5 text

What is (Riverpod’s)Provider? ● An object that encapsulates a state and allows listening to the changes. ● Allows easily accessing to a state from multiple locations. ● A replacement of patterns like Singletons, Service Locators, Dependency Injection, or InheritedWidgets. @riverpod String helloWorld(HelloWorldRef ref) { return 'Hello world'; }

Slide 6

Slide 6 text

Code generation ● Riverpod 2.0 supports code generation. ● It automatically decides and creates the best provider for the use case. ● Code generation is pretty common pattern in Flutter or Dart programming. ● Static metaprogramming feature is coming to dart.

Slide 7

Slide 7 text

Code generation - Examples // Without code generation final fetchUserProvider = FutureProvider.autoDispose.family((ref, userId) async { final json = await http.get('api/user/$userId'); return User.fromJson(json); }); // With code generation @riverpod Future fetchUser(FetchUserRef ref, {required int userId}) async { final json = await http.get('api/user/$userId'); return User.fromJson(json); }

Slide 8

Slide 8 text

Different kinds of Providers Provider FutureProvider StreamProvider NotifierProvider AsyncNotifierProvider - New in 2.0 StateProvider - Legacy StateNotifierProvider - Legacy ChangeNotifierProvider - Legacy StreamNotifierProvider - New in 2.0 Function Provider Class Provider

Slide 9

Slide 9 text

Basic Provider @riverpod Repository repository(RepositoryRef ref) { return Repository(); }

Slide 10

Slide 10 text

Future Provider @riverpod Future fetchUser(FetchUserRef ref, {required int userId}) async { final json = await http.get('api/user/$userId'); return User.fromJson(json); }

Slide 11

Slide 11 text

NotifierProvider @riverpod class Todos extends _$Todos { @override List build() { return []; } // Let's allow the UI to add todos. void addTodo(Todo todo) { state = [...state, todo]; } }

Slide 12

Slide 12 text

AsyncNotifierProvider @riverpod class AsyncTodos extends _$AsyncTodos { Future> _fetchTodo() async { final todos = jsonDecode(await http.get('api/todos')) as List>; return todos.map(Todo.fromJson).toList(); } @override FutureOr> build() async => _fetchTodo(); Future addTodo(Todo todo) async { state = const AsyncValue.loading(); state = await AsyncValue.guard(() async { await http.post('api/todos', todo.toJson()); return _fetchTodo(); }); } }

Slide 13

Slide 13 text

How to read a provider ● ref object is accessible from a widget or another provider. ● ref.watch() to observe a provider change. ○ It triggers rebuilding a widget or provider when it’s changed. ● ref.listen() to react to a provider change. ○ It calls the callback function registered when it’s changed. ● ref.read() to obtain the state of a provider. ○ It only read once. Whenever possible, prefer using ref.watch over ref.listen or ref.read to implement a feature. This way, the application becomes reactive and declarative.

Slide 14

Slide 14 text

Rebuild with a state change @riverpod class Counter extends _$Counter { @override int build() => 0; void increment() => state = state + 1; } class HomeView extends ConsumerWidget { const HomeView({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final count = ref.watch(counterProvider); return Text(count); } }

Slide 15

Slide 15 text

Read the current state without observe @riverpod class Counter extends _$Counter { @override int build() => 0; void increment() => state = state + 1; } class HomeView extends ConsumerWidget { const HomeView({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { return Scaffold( floatingActionButton: FloatingActionButton( onPressed: () => ref.read(counterProvider.notifier).increment(), ), ); } }

Slide 16

Slide 16 text

Listen to react to a state change @riverpod class Counter extends _$Counter { @override int build() => 0; void increment() => state = state + 1; } class HomeView extends ConsumerWidget { const HomeView({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { ref.listen(counterProvider, (int? previousCount, int newCount) { print('The counter changed $newCount'); }); return Container(); } }

Slide 17

Slide 17 text

Combining provider states @riverpod String city(CityRef ref) => 'London'; @riverpod Future weather(WeatherRef ref) { final city = ref.watch(cityProvider); return fetchWeather(city: city); }

Slide 18

Slide 18 text

How does provider works? ref.watch(aProvider) aProvider ref.watch(aProvider) bProvider ref.watch(bProvider) Map(GlobalScope) Automatically Initialize the provider when the first time it’s watched Automatically Dispose the provider when there’s no watchers

Slide 19

Slide 19 text

How to install

Slide 20

Slide 20 text

Install the dependencies $flutter pub add \ flutter_riverpod \ riverpod_annotation \ dev:build_runner \ dev:riverpod_generator

Slide 21

Slide 21 text

Wrap the entry widget with ProviderScope void main() { runApp(ProviderScope(child: MyApp())); }

Slide 22

Slide 22 text

Watch and re-generate the code # Before starting coding $flutter pub run build_runner watch Build Runner Extension

Slide 23

Slide 23 text

Demo - Todo app GitHub

Slide 24

Slide 24 text

Home work! Here are some ideas to get familiarized with Riverpod. ● Fork the demo app code. ● Add the delete feature. ● Add the edit feature. ● Convert selectedFilter into Provider in todo_page.dart. ● Share your achievements or get help from discord.

Slide 25

Slide 25 text

Bonus! ● Riverpod 2.0 documentation ● Riverpod lint - Highly recommended! ● Riverpod snippet extension for Visual Studio Code ● Build runner extension for Visual Studio Code ● Code with Andrea’s tutorial - Awesome tutorials!

Slide 26

Slide 26 text

Thanks!