Discount !! E-commerce App With Backend Source Code Video and Voice Chatting App Firebase Chatting App Source Code Complete Gym App BLoC State Management Source Code Complete Study App Buy Ticket Booking App Source Code Buy Travel App With Backend Source Code Complete Chat App Udemy Course Special Offer Discount !! Online Learning Course App (BLoC) Online Learning Course App (Riverpod) Online Learning Course App (Getx) Discount !! Shopping App (Provider) Cool Flutter Game Nodejs Flutter Complete App
Riverpod 2.0 has big change then the earlier versions. It introduced auto generated providers which is convenient and less error prone. It has also introduced two new providers NotifierProvider and AsyncNotifierProvider.
it also introduced another two new providers. Previous versions have seen six providers. You can still use the older version of Providers
.
In this new version NotifierProvider and AysncNotifierProvider are encouraged to use more. Since the new version depends a lot more on the auto generation of code, we will first see how to auto generate Providers with a package name
riverpod_generator
Go ahead and install the plugin. At the same time make sure you install riverpod latest version at least equal to 2.0 or above.
Let's take an example. Previously we could have a Provider like below
final stringLabelProvider = Provider<String>((ref) => 'Hello World');
The above providers is manually typed in and you mention the provider type. Here we return a Provider which gives us a String.
Annotation & function name
Now we do the same using riverpod annotation. It's a special syntax. It's like below
@riverpod
With this Flutter would know that, it needs to generate riverpod code. But how does it do it ? You need to give it more information, you need to provide it with a function.
@riverpod
String StringLabel(StringLabelRef ref)=>'Hello World of Riverpod';
The above one is a function that would generate a Riverpod provider. See the annotation at the top. With this kind of syntax you don't need to mention the Providers you want. Riverpod will auto generate the Provider for you. All you need to do it mention the return type of the function
.
In the above case, we need a Provider to manage our String. So Riverpod will auto generate a Provider that will help us manage a String.
Even though it looks like there's more code write this time, but this is still cool since you don't need to mention the Provider type on your own. Previously it was confusing to mention since there are six types of Providers.
We are two more steps away from the auto generated code. You need to
√ mention where to put the auto generated provider code
√ run a special command to generate the provider
File path name
You need to tell riverpod where to generate the file and you need to give it a name. The name should be similar as your current file name.
In this case our out function mentioned is in main.dart
, so the auto generated file would be main.g.dart
. You need mention at the top right below other imports.
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';
part 'main.g.dart';
You see we put the file name as part of our project
and we put below other imports.
Run command
This is the last step. We need to run a command to auto generate the code. The is is given as below
flutter pub run build_runner watch --delete-conflicting-outputs
for the above command to run make sure you have installed the below plugin
build_runner:
After running command look at the file below.
So now our main.dart looks like below
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter/material.dart';
part 'main.g.dart';
//final stringLabelProvider = Provider<String>((ref) => 'Hello World');
@riverpod
String StringLabel(StringLabelRef ref)=>'Hello World of Riverpod';
void main() {
runApp(ProviderScope(child: Home()));
}
class Home extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Text(
ref.watch(stringLabelProvider),
style: const TextStyle(fontSize: 30),
),
),
),
);
}
}
You will also see there's a main.g.dart in our lib folder. That file is scary, but you need to look at the bottom part of the file.
You will see the above code in the bottom of the main.g.dart
. Here's a provider that's been generated for us and it's stringLableProvider
.
The Provider stringLableProvider we used in our UI code.
NotifierProvider
This is a new provider, this one is supposed to replace ChangeNotifierProvider, StateNotifierProvider and StateProvider.
Let's see how to use Riverpod 2.0 NotifierProvider for reactive state and change state of the app. Here we will first create a class and our class would extend
Notifier. Here we will do everythign manully. You can still generate code using riverpod generator
plugin
With Notifier you need to mention your state variable type. In this case we will have a string and it should be reactive. so we will mention it.
class NewStringLabel extends Notifier<String>{
@override
String build() {
return 'dbestech';
}
void toCamelCase() {
state = '${state[0].toUpperCase()}${state.substring(1).toLowerCase()}';
print(state);
}
}
Next we also have to override the build method. Build method should return String type since our Notifier return type is String. You may understand it the other way,
Since build method returns String type, Notifier should return String too.
At the same time, we have a method name toCamelCase(), we will call this method using our Provider.
And after that we need to expose our state to the outside world.
We will do that using NotifierProvider. NotifiterProvider would take our custom class and Notifer type.
final newStringLabel = NotifierProvider<NewStringLabel, String>(NewStringLabel.new);
Previously you would have done it using Provider, StateNotifierProvider or StateProvider.
See the complete code for this example.
class NewStringLabel extends Notifier<String>{
@override
String build() {
return 'dbestech';
}
void toCamelCase() {
state = '${state[0].toUpperCase()}${state.substring(1).toLowerCase()}';
print(state);
}
}
final newStringLabel = NotifierProvider<NewStringLabel, String>(NewStringLabel.new);
void main() {
runApp(ProviderScope(child: Home()));
}
class Home extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Consumer(
builder: (context, ref, child) {
final String val = ref.watch(newStringLabel);
return ElevatedButton(onPressed: (){
ref.watch(newStringLabel.notifier).toCamelCase();
}, child: Text(val));
},
),
),
),
);
}
}
If you have list of objects like custom objects, String or integer, you may still use Notifier and NotifierProvider. Your Notifier may return list of objects. In our below example we return list of Strings.
class StringGenerator extends Notifier<List<String>>{
@override
List<String> build() {
// TODO: implement build
return [];
}
void addString(String randomStr){
state = [...state, randomStr];
print(state.length);
}
void removeAString(int index){
state.removeAt(index);
state = [...state];
}
void removeString(){
state = [];
}
}
var strNotifierProvider
= NotifierProvider<StringGenerator, List<String>>(StringGenerator.new);
Like in the code, we have addString(), removeAString() and removeString(). They all operate on Strings using state object.
Our state object is held by Notifier class. And this notifier is exposed to the UI using NotifierProvider.
Pass WidgetRef
Say you have a controller and you need to pass WidgetRef object globally to the controller and use the context of the ref object? How would do it? Actually it's easy. Every controller needs to be initialized.
Since controllers needs to be initialized, you may create a constructor of the controller and pass WidgetRef object from the UI and use it.
See how I am initializing and passing the ref object to the controller. Now we would be able to grab the ref object in the controller.
Let's see how to get it on the controller
See how I accepted WidgetRef in the constructor, and use ref.context
inside showDialog
.