Search

riverpod

// main.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:untitled7/screen/home_screen.dart'; void main() { runApp( ProviderScope( // wrap MaterialApp with ProviderScope child: MaterialApp( home: HomeScreen(), ), ) ); }
Dart
복사

Provider

1.
Base Provider
2.
Can return any type
3.
Can have nested provider

StateProvider

1.
Use when user wants to directly manange
2.
Can return simple data type (int, double, String, etc.)
3.
Don’t use for Map, List, etc. frequently (possible)
4.
Limited to simple logic
a.
number++
// riverpod/state_provider.dart import 'package:flutter_riverpod/flutter_riverpod.dart'; final numberProvider = StateProvider<int>((ref) => 0); // add <Generic>
Dart
복사
// screen/state_provider_screen.dart import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:untitled7/layout/default_layout.dart'; import 'package:untitled7/riverpod/state_provider_screen.dart'; class StateProviderScreen extends ConsumerWidget { // change StatelessWidget to ConsumerWidget const StateProviderScreen({Key? key}) : super(key: key); Widget build(BuildContext context, WidgetRef ref) { // add WidgetRef ref to the parameter final provider = ref.watch(numberProvider); // add ref.watch(#riverpod state); return DefaultLayout( title: "StateProvider", body: SizedBox( width: MediaQuery.of(context).size.width, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( provider.toString(), // how to READ data ), ElevatedButton( onPressed: () { ref.read(numberProvider.notifier).update((state) => state + 1); // how to UPDATE data }, child: Text( "UP", ), ) ], ), ), ); } }
Dart
복사

StateNotifierProvider

1.
Used to manage data directly in UI (similar to StateProvider)
2.
can manage complex data type
3.
return class inhereted by StateNotifier
// model/shopping_item_model.dart class ShoppingItemModel { final String name; final int quantity; final bool hasBought; final bool isSelected; ShoppingItemModel({ required this.name, required this.quantity, required this.hasBought, required this.isSelected, }); }
Dart
복사
// riverpod/state_notifier_provider.dart import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:untitled7/model/shopping_item_model.dart'; // StateNotifierProvider converts class inherited by StateNotifier to Provider // first generic of StateNotifierProvider is the class inherited by StateNotifier // second generic of StateNotifierProvider is the generic state by StateNotifier final shoppingListProvider = StateNotifierProvider<ShoppingListNotifier, List<ShoppingItemModel>>( // return class inherpited by StateNotifier (ref) => ShoppingListNotifier(), ); class ShoppingListNotifier extends StateNotifier<List<ShoppingItemModel>> { // must add what type we will manage // must have constructor ShoppingListNotifier() : super( // super constructor give data related to the type stated on StateNotifier // i.e. <List<ShoppingItemModel>> [ ShoppingItemModel( name: "Kimchi", quantity: 3, hasBought: false, isSelected: true, ), ShoppingItemModel( name: "Ramen", quantity: 5, hasBought: false, isSelected: true, ), ShoppingItemModel( name: "Pork", quantity: 10, hasBought: false, isSelected: false, ), ShoppingItemModel( name: "Watermelon", quantity: 2, hasBought: true, isSelected: false, ), ShoppingItemModel( name: "Cake", quantity: 5, hasBought: true, isSelected: true, ), ], ); // have to state what data it will have on init void toggleHasBought({required String name}) { // state is provided by StateNotifier automatically // the data is set to the first parameter on super constructor state = state // if state name is same as given name by parameter // ? change value : return e (original) .map((e) => e.name == name ? ShoppingItemModel( name: e.name, quantity: e.quantity, hasBought: !e.hasBought, isSelected: e.isSelected, ) : e) .toList(); } }
Dart
복사
// use case import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:untitled7/layout/default_layout.dart'; import 'package:untitled7/riverpod/state_notifier_provider.dart'; class StateNotifierProvider extends ConsumerWidget { const StateNotifierProvider({Key? key}) : super(key: key); Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(shoppingListProvider); // how to define state return DefaultLayout( title: "StateNotifierProvider", body: ListView( children: [], ), ); } }
Dart
복사

FutureProvider

1.
only used in Future type
2.
Often use in API request result
3.
No complex logic and no trigger restart action
a.
Use StateNotifierProvider if needed

StreamProvider

1.
return only Stream type
2.
Used when user has to return API result in stream
a.
Socket
Provider Type
return type
use case
Provider
any type
Data Caching
StateProvider
any type
simple state data
StateNotifierProvider
data inhereted by StateNotifier
complex state data
FutureProvider
Future type
API request Future result data
StreamProvider
Stream type
API request Stream result data

ref.read vs ref.watch

ref.watch build everytime when there’s an update in return data
ref.watch is only used in UI code related data
ref.read return data only once when it is called
ref.read is used in places like onPressed callback, where there is trigger action
ref.read(#stateName.notifier).update((state) => state + 1);
ref.read(#stateName.notifier).state = ref.read(#stateName.notifier).state + 1;
provider (final provider = ref.watch(numberProvider); is often used right below the build

Reference