Flutter Riverpod 2 Tutorial for Beginners | Riverpod Generator

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we are going to dive deep into riverpod we will learn about all the essential components of riverpod limitations we get while using it and solutions to them one of the solutions I've covered is the next big thing in the riverpod world so make sure to watch the video till the end to know more about it let's start the video by understanding why we need report in the first place there are some problems with provider which cannot be fixed some of those problems include confusing and tedious syntax from proxy provider multiple providers not having the same return data type and the infamous provider not found exception to counter these problems riverpod was written however ropod is not just a state management solution anymore it is also a replacement for many design patterns like Singletons dependency injections and service locators it also helps in fetching caching and canceling Network requests while also handling the error cases to get started head to prospect.aml file and make sure you have the latest version of flutter riverpod installed riverpod is divided into three packages hooks River pod flood a riverpod and River pod hooks River pod is used with flutter hooks flutter River pod with the flutter SDK and the driver pod with dart programs that means you can create clis using riverpod after having that in place go to the main.dot file wrap your root Widget the widget that's passed in the run app with a widget known as providerscope this provide a scope widget is a constant and it comes from flutter evapot package this provider scope keeps track of all the providers and ensures that there is no leakage of State in spite of the providers being declared globally Global Declaration of providers or variables in general means if suppose I have a variable like string name and I've declared it outside of any function and outside of any class I've declared it globally usually Global declaration be it of variables or providers should be a problem because of mutability issues meaning if a non-constant variable like this name is declared its value can be changed by any function for example if I have the main function right here I can change the value of name over here right so I can type my name as revenue and I can do the same thing in home screen here I can just import main.dot file and set it to Noman imagine this for hundreds and thousands of files do you think it's a good practice to do this it's not because it would be very difficult to know which function changed the value of name and if we ever want it or not and to find it will be a big task and we generally don't want to do that so you might think if this is prohibited why does provider or riverpod even do this the reason for that is the providers declared globally in riverpod are immutable and this is for all the providers in riverpod they all are immutable except one which we will talk about in a while anyways now let's just remove this line and get to the first type of Provider which is provider itself riverpod has multiple providers which can give us access to State whatever state we want to access and for them each provider has its own purpose so the very first type of provider is provider it is called provider if you are coming from provider package you already know about it as the name suggests it is an object that provides data to Widgets or other providers it is a read-only widget and cannot update the value inside of it it can be used to provide primitive non-primitive data types and even instances of classes to create a provider what we do and this follows for all the type of providers not just for provider we put a final because the value cannot be changed and then we give the name of the type of the provider so I'm just going to provide name provider and always like to suffix it with the provider because suppose if I have this class right here and I've named this provider as name and here I'm using an instance variable of the data type string so I have string name over here I'll get pretty confused right if I want to access this name provider or the name variable that I've created a wire that's why I like to suffix it with provider so that there's a clear distinction then is equal to and then the type of the provider the very first type of a provider is provider itself so we have provider and here we will just create a function but you can see it gives us an error the reason for that is this function gives us access to something known as ref which is provider ref this provider ref will allow us to talk with other providers we'll take an example for that later on but for now all you need to know is that provider refs will allow us to talk with other providers now if you hover over this you can see it is of the type provider null but that's not what I want I don't want to return null if you don't pass anything what this is doing is basically returning null like this and that's why the data type over here is null however I want to return the name so I'm just going to have rivan returned over here and now if you hover over this it's of the type string it automatically detects the type that you are returning however if you want you can just add a data type over here so you can just write string over here and that works too but if you pass an into wire and return a string it will throw an error for you so you have to change it either over here or just convert it back to string if you have int you'll return 2 like this and a shorter syntax to return from this is since this is a function we'll just create an arrow function so we'll just have something like this done since this is a function we have an arrow function right here but since I'm returning a name I'm just going to create something like this now now what I want to do is whatever name I've returned over here I want to display it in this screen so it's in a separate file itself I don't have the name property over here I don't have access to name provider over here I have access to it in a different file so how am I going to do that well for that we have the reading properties there are two ways to read a provider in any file so since this provider is globally declared you can Rewritten any file that you want and it will work for you so if you want to read it in the home screen there are two ways of doing it first one is using a consumer widget a wire this consumer widget is given by the flutter riverpod package so you just need to remove the stateless part and add consumer so you have consumer widget and then here you can see we are getting the error to fix it just put in a comma and have widgetress this widget ref is similar to the provider riff that we had over here only difference between these two is widget ref allows you to communicate from widgets to other providers that's what we are going to do we are going to make use of this refs so that we can call the provider because we are in a widget right so from this widget we are going to contact this provider however this ref will allow you to communicate from one provider to other provider obviously so that is the difference between widget ref and provider F now to display the value what can you do well you can have final name is equal to now you just want to extract the data given from this provider how will you do that well again there are multiple methods for this I'm going to show you the three methods first one is ref.watch you want to pass in the name of the provider our provider is name provider so we have that so what we are doing is watching the name provider and you have access to name and you can see it enforce it that it's of the type string we have nowhere mentioned it is string but since we our provider has already decided that this is of the type string it knows yeah whatever provider we are listening is of the type string which is pretty cool we always need to have data types for our variables now we can just take this name property and have it over here also remove the constant because we are watching it from a provider now we can restart the entire application and here you can see Demand on our shows up if you change the value here for example something like this this doesn't get updated because changes on hot reload example when we just click Ctrl s in provider is not supported in flutter riverpod package so you just need to restart the entire app and after you do that you get access to Revan now what is the other type of reading method as I said there are two types of reading one is a consumer widget other is not using a consumer widget and instead having a stateless widget right here and then you don't have access to widget ref anymore you'll also remove this ref and here in the column you're going to wrap it with a builder method or a build a widget and then you're going to change it to consumer now the Builder will give access to context ref and child I'll explain it to you what is this consumer well we wrapped our entire widget with the consumer widget first now we have access to a widget where we can only listen to a certain part for example if we add something like our name again over here so we have ref.watch name provider and we are storing it to name what we have already done before but now we have access to context ref and child context we know is build context child we already know but ref is again widgetress so we have the exact same thing that we had earlier but instead of changing this from a state list to Consumer widget you need to wrap the widget tree with consumer so if you restart the app and see it's the exact same thing everything is the same so now you'll think what is the difference between consumer and consumer widget right I mean both are the same thing aren't they well the basic difference between both of them is consumer widget and consumer widget when we had our provider something like this over here which widget traffic wire the entire widget would rebuild when there was a change in the variable so suppose the value of name changed of course it's not possible with provider but if the name value changed over here with some other type of Provider that we are going to look at and things would get much more clearer then then the entire widget will rebuild now you can see we had an app bar and it didn't depend on this name text so even if the name changed this scaffold would rerun that means the app bar would get rebuilt and the body dependent on the name of the user would also debent but in a likely scenario we just want this Center widget to rerun not the entire scaffold you know that's why we have used consumer instead of consumer widget however if our app bar also wants the title and the title should be the name of the user in that scenario we can't use consumer I mean of course you can you can wrap this with the consumer method just like we did earlier right so you can just remove this line from here you'll have it right here and then you'll have context ref and chat so you have it you can wrap the scaffold with consumer but what's the point of just nesting things up it's not a great situation we should always prefer not nesting much you know it creates a lot of confusion especially when the widget Tree Grows so that's why to avoid it we have the consumer widget so with this we get access to widget ref over here and now when we want we can return this consumer remove this consumer sorry and then we have access to name and now whenever the name changes this scaffold will re-run and this is a likely scenario because the app bar also depends on name and even this widget however if this does not depend and there are other widgets that do not depend you do not want to rebuild them so if you have something like a bottom navigation bar as well you don't want it to rerun or rebuild so try and divide your application or your widget tree into smaller parts so that whenever necessary you can directly use consumer widget and if not you don't have to use consumer right now after having that simplified you can see ravan and ravan shows up and I also mentioned that we have different types of methods to read a variable from using ref right once we have access to ref we have different ways of reading it first one is ref.watch second one is something like let's just name it name read so you have ref dot read and then you can call it name provider so what is the difference between ref.watch and ref.read well ref.read is a one-time thing only so when you just want to read the name of the provider so like we have this so we want to read the value of the name provider just once then we use ref.read however if you want to continuously keep listening so that you get to know if there are any changes or no changes you can use watch so generally it's recommended not to use ref.trade in build method it should generally be used outside of the build method when you have a stateful widget and is generally recommended that you use watch inside of the build function and not outside of the build function we are going to take in a look into some example and things will get much more clearer when we have other types of Provider you'll notice the differences and you'll notice when to use what in our case we just have a provider for now so things might get confusing you might also think what's the purpose of watching a provider when it's only a read-only widget right we can't update the value of Provider outside so if we have name provider we can't go and change it over here meaning if I want to change it so example we have name provider and I want to change it suppose I want to assign a value to it I can't do it something like this right I just can't do this you can see it gives us an error or generally this is done using the ref because ref gives us access to these methods so we have refs Dot watch name provider and then if you try to set it equal to something else it won't happen it's just not possible for providers so there are two important questions that you'll ask first one is what if I have a stateful widget right so if this is a stateful widget and you call this suppose my widget only and then you want to have the same returns scaffold part there are some changes in this that's why you made it a stateful widget but let's not discuss about it but you have the exact same return on data types from your your widgets are depending on name how will you get access to widget ref over here well obviously of course you can just wrap it with the consumer and get access to ref otherwise instead of using consumer widget that's mentioned over here you'll have to pass in consumer stateful widget a consumer State and here we'll also extend the consumer state now you can see all of our errors are gone actually we should be getting an error in the build method right because here we had access to widget ref and when we didn't put it we were getting this error why are we not getting it here the reason for that is widget ref is present in the consumer State itself the reason for that is similar to context if you want to use it in life cycle methods like NH state or this pose you don't have to do anything you directly get access to ref over here you can see we have widget ref and it's coming from the consumer State it's no longer a state it's a consumer State that's why we have access to the refs so now what you can have is very simple again just final name and to read it of course we are in the build method so ref.watch and then we'll just have name provider it's generally recommended that you use ref dot read inside of these life cycle State methods or inside of the functions that you create like this so you have ref dot read over here don't use ref dot watch it's not recommended because watching creates a listener that will continuously listen to the changes built but read will also create a listener but it will just do a one-time listening part it won't continuously track all the changes in your data inside of the provider all right now let's just remove it we have our simple stateless consumer widget let's have that then second question that you might have is how do I change the value if I want to I said provider is a read-only widget how can I make sure that I can change the value from an input over here so for that we have the second type of Provider which is State provider State provider is to use to update the value from outside which is not possible using the provider it is like an upgrade over the normal provider so how do we do that well we have access to let's say name provider here we'll just have state provider instead of provider again we love verif as I said this is the convention for all of our providers that we'll create and then the initial value so our initial value is going to be Revan as well now you can remove this I just kept it here so that you can compare the syntax of course if you want you can pass in a string over here but now what I'm going to do is kind of different initially I want the value to be that is to be returned as null so here I want to define the value that's being written as null so what can I do well in the state provider you can see we have mentioned a return data type if we don't this also correctly identifies the type which is null but that's not what we are going to return initially the name provider is null because the user hasn't typed anything but later on it will have a value so here we are going to have a return data type of string with a question mark which means it can have a string value or it can have a nullable value so now in the home screen all of this are in errors because this name now is of the data on data type string with the question mark and you can see we don't have to do any more changes you can read all the providers inside of the build method using ref.watch we have six different type of providers in flutter riverpod package all have the same syntax to do and all use consumer widget and widget ref to do so so now what can I do here well I'll have a text field over here which will ask the user for their input and whenever they're submitted I want to change the value but before adding that logic I'll just have a empty function and here you can see name is of the return data type nullable so I'm just going to have something like this done this basically means that if the provider is null we are going to have an empty string and if it's not null then we are going to have name provider it says a shorthand syntax war is not equal to null then we have name provider ref dot watch name provider otherwise this but you can see it gives us a warning because there is a shorter method for this which is this right here now if I restart you'll see nothing shows up the name is empty because it is null the name value name provider is null which means it will give us an empty string but in the text field what I'm going to do is update the value of the name provider because this is a state provider so I'm just going to have ref and how do we update the value well we can use ref.read and this is the key point to note ref.read is used in life cycle methods if we are in a consumer stateful widget it is used in functions that we create and that's why we are having it right here because this is a function if we want to extract it we can have void on submit and we can extract it in a function outside and if it's a function outside what do we do well we just use ref.read right I've already mentioned but here we don't have access to ref so we'll get access to ref from the parameter here and then here we are just going to call the on submit function pass in the ref which is from the parameter here and the value which is from this parameter and now since we are in a function outside we can use ref.read this is a main difference make sure to do so if you don't it will give you an error now after reading it you can see it will again give us access to a variable so we have final name it's equal to this and this is again a question mark it hasn't updated of course why will it update right we are just reading it and reading is just a one-time getter so now what can we do well I want to update the value so I'm just going to have ref.read and it there should be some method on it right because it is immutable of course all the providers as I said are immutable except the one provided that I'm going to take on in just a while but this one is also immutable so we can't have something like this done over here so what can we do it should have a method which will allow us to change its value so do we have it no we don't because this is of the type string and it's giving us string Methods so how can we get inside the read method we lab dot Notifier and this dot Notifier will allow us to change the value so now when we do dot over here you can see we have access to new methods the string Methods are now gone having dot Notifier converts this to some new variable which we'll see over here so now when you access to this it's of the type State Controller of string it's not string anymore but if you want access to State you can just do like this but there's no point of doing this because it's the exact same thing that we get after doing this anyways so now that we have notified here we can get access to an update kind of method right so here we have it update and after having update we get something known as state aware this state is the previous state that means the current state of a provider and here we want to return what should be the updated value so in our case it's the state is empty as of now and here we need to return what do we need to update the value with so our updated value is let's say going to be value what is the value whatever value we get over here which is whatever the user submits so now if I restart the app and then just type Revan over here and then click on enter you can see it changes both the places so these are the two basic types of Provider now there comes a third type of Provider which is an upgrade over the state provider State provider is used for very simple values like a string that we had over here and integer value a double value a Boolean value but what about complex values for example if you want to modify or manipulate the values inside of a class what if I want to update a map there will be many functions for that for example if you have a user model like this over here it will have many of its functions right for now we just have two properties in the user but a general user will have many more properties in a real application so we need to create a function for them so that we can change the name value we I'm not saying we can't do that with the state provided it's it's definitely possible but our logic will be lying around in our widgets so we don't want to make make our logic lie around in the widgets as programmers we want our logic to be together in a single place and most likely a class so what can we do well for that purpose we have the combination of State Notifier and state Notifier provider what is this going to do well let's look at an example to understand it better so if you have a user here let's just create a class called user Notifier this is a model right this is a user model and now this user Notifier will contain all the methods to update the name and the age of the user so what can we do now well we want it in collaboration with State Notifier so we'll extend this class with State Notifier this state Notifier will give us access to State a variable which can be used to update the data and what is that data going to be well whatever data type we pass in over here the state will be of that type in our case it's going to be user because we need to manipulate the values of the user model right we want to update the values of name and age so we'll have extend State Notifier and then we'll pass in user aware now you can see we are getting an error the reason for that is we need to create a Constructor which will call Super dot state and now the error goes away so what have we done we have created a class that extends a state Notifier and we have given it a return on data type this data type is going to decide the state of this user you can see this is user now but if I change it to a Boolean value this will become Boolean simple now after having this as user I want to create simple functions that will allow me to change the name and the age of the user so like as always a very simple function for this will be void update name and here we'll get access to something known as n which is the updated name that the user has passed in the text field over here and then we have n is equal to name sorry name is equal to n so what will we have we'll have state which is the user model and this should be equal to we need to update the value of this user class so we'll have state dot name and how exactly are we going to do that well I don't know it should be something like state DOT name is equal to n but that's not possible because the properties of this user class are immutable and actually this entire class is immutable so this is a constant user since this class is immutable we can't change the values of this user class once assigned we can't do that so what can we do well one solution would be to do state is equal to user then we pass in the new name and the age will be state DOT h and there we go but this is a very lengthy approach right because if we have more Fields over here for example if you have ages like uh if you have values like gender and all of the user Properties phone number and all email uid this will get pretty big and doing this for almost every function every property will be very difficult for example we'll have update age doing the same thing for it will be very difficult so what can we do well if you just click on this bulb icon and if you have dot data class generator vs code extension you will get access to this with which you can generate a data class it will give you methods like copy width which is very useful for us and much needed a from map to map function and two Json from Json which we are going to use just after some time when we get to something known as future provider a two string is equal to equal to operator and a hash code operator or override method so after getting all of this my point is now you can just do state is equal to State DOT copy with and name should be set to n so what this is going to do is copy all of the same properties of state but only change name variable to whatever is passed to this argument right here and this will do some magic for us let me show it to you now I'll go to the main.dot file and now instead of having State provider I'm going to create final user provider which is equal to State notify a provider here we use State Notifier and to provide the state Notifier to expose this state node F fire we'll get access to ref wire and then we can just provide the user note a fire class make sure to return a user Notifier class because if you try to give some value like a string it will give you an error because this wants a return data type of a state Notifier class it doesn't want a string or any primitive data type or even non-primitive it just wants a state a class that is inheriting from State node to fire so now we can just have user Notifier and you can see it asks us from in the parameter to give the user value because here we have asked for the state so what should be the initial state is what it's asking so you can pass the initial State and if you look over here it is asking for the data type of user as I've already said if you want to give it a Boolean and come back over here you can see it asks for Boolean it all depends on what you pass in over here and it's very important what you pass in over here so here what is our initial State going to be well a user model with the name empty and age 0 and then we can have a constant user now we can just go to the home screen for the on submit we can comment it out and here let's remove this line what do we want we want the user model so we are final user equal to ref we are in the build function so we'll have ref.watch and then it's said to have user provider and if you hover over this it is saying that the return data type is an object but that's not quite what we want because now if I try to do user.name you can see the property name does not exist over here and that's true because it doesn't know that it's of the type user to fix it you can do something like this so we have as user now if you're over with this this is of the type user but I generally don't like this approach because doing explicit conversion means doing it literally everywhere and if again we have hundreds and thousands of classes and files doing it everywhere doesn't make sense so again we'll go to the main dot dot file and here for a state Notifier provider will give it a type so our first data type is going to be user Notifier because that's the class that we are returning so vlab user Notifier and then we need to pass in a second data type which is user so first is the class that you are returning and second is the state of that class so our state of the class is user more user so we'll just have user return over here now in the home screen you can see it identifies user dot name and here we can have user.h.2 string because this is of the data type end now whenever the user submits actually before doing anything else let's restart we'll see 0 and empty string over here now whenever the user submits a value in this text field I want to update the thing so I'm just going to remove everything out and I'm going to have ref and again we are in a function and whenever we call another function we generally use ref.read you can see even here it gives us a tab or calling read inside build if the value is used only for events so if you have counter ref dot read it's said not to use it however in the on pressed it says to use this line all right now we want to read or update the value from user provider and now if I have access to this you can see again it's not giving me we had seen it earlier doing read gives us access to the user model not any method that can change its value and we thought to fix that we called the dot Notifier method and then we have access to new set of properties because this is now of the type earlier it was State Controller now it is user Notifier because this is State Notifier earlier it was State Controller when we had State provider but now since we have state Notifier provider doing Dot Notifier gives us access to this entire class so thus we have user Notifier now so if we have access to this entire class that means we have access to the instance of this class we can easily call this method can't we so we can just call Dot update name and we there we have it but that's not it we also have access to and after that we can just pass in the value which is what we get from the argument here now we can remove this user no need of it because update name doesn't really give any value you can see this is of the type void now I can restart the entire app and now if I try to change it for example like this you can see it changes you might think what is the difference but as I said the difference is that we can create multiple functions and all of them will reside in just one single class as developers since we are in need of something robust that's easier to test we generally use the state Notifier and state Notifier provider we don't use State provider because there are very less use cases of having to change a very simple value in bigger application and all of our business logic Now lies in just one class so if you want to have another property now which is void update h here you will get access to integer so this will be a and then you'll have state is equal to State DOT copy with a and then you have suppose another text field here and you create another function also which is on submit age and you call update age and then pass the value that's coming assuming that the user is kind enough to just pass in a normal integer value like 10 or something even though it's a string it can easily convert using n dot pass so now if I just restart and type in something like 10 the reason this happens is because I'm not taken this function and put it right here after doing this and restarting the app now if I do something like 10 you can see the value updates over here and when I do something like this it updates over here perfect and you can do it for as many properties as you have it's a better way of doing it one thing to note is whenever you update the value of State aware only then will all the clients that are listening to it for example this line right here it's listening to this user provider right it's listening to the changes that are happening in the use of Provider so only when the value of this state changes will this rerun so if you do everything else for example if you try to manipulate the state like n is equal to an empty function a empty string and then you know just try to do something like n is equal to doctor plus n and something like this but you don't do state is equal to State DOT copy with name and if you don't do this nothing will get updated so now let me show you a demo if I restart the app and do something like this you can see no update happened you change the value of n but you haven't changed the value of our simple name property and that is not good that's why make sure to change the value of State even if you do state DOT copy with it will not run because you've not really given the state its value so do this another thing is that the state over here is immutable so if we take this state and try to use it or update the value over your it's immutable for example something like here we have dot State we can't assign it to another user model right it is immutable outside of this user Notifier class however inside of this class you can change the value of state and third and the final thing about State Notifier and state Notifier provider if what if you don't want to pass the value of the state from here you directly want to Define it over here in this class itself in that case you can remove it from the user Notifier go to the user Notifier class remove the super dot nodes super dot State and then you can have a colon super and then you can pass in the state what is the state going to be well exactly this function model right name and age zero so the difference over here is when we called super dot State we are basically telling that whatever we get the value from here we are just going to take it in and notify our state Notifier class because that's what it wants it wants access to state but now what have we done we have removed the call from the Constructor saying yeah I don't want to accept it from The Constructor that means I will not pass it over here and instead I'm going to have colon super which means it will call the parent class or the inherited class the inherited class in this case or the class that we are inheriting from a state Notifier so we just call the super method that means we call the Constructor of the state Notifier class this part right here and you can see it wants access to State and we are just passing in the state which is the constant user with no name or an empty string and 0. it will work just as same but instead of taking it from the parameter here we are doing it from here just a very simple thing and an explanation of what was happening when we use super dot State and super way up we just telling a state Notifier class and telling it about this initial State and then of course we can change the later value of State how and whenever we want okay now the last thing which I forgot to tell you is what if you want to run a Constructor that means you want to do something as soon as this user Notifier class gets initiated or gets run so you can just do something like this and there we have it you can just make your calls or whatever so if you want to update the name as soon as something happens you can just pass in a and do that now if you restart our initial name should be a and H should be zero and this is what happens we have a and 0. so this is how you run a Constructor but anyways I'm just going to have this right here having knowledge of State no defier I want to give you knowledge about the third type of ref property that we had I told you we can read from using ref from using three types we have rev dot read we have rev dot watch and the third one is using the select method so the Syntax for this is having final user is equal to ref Dot let's call it user select we are in the build function so we'll have ref.watch then we are going to have user provider and over here we have access to a method called select and you can see it gives us a value which is of the type user and we have something you don't know what's going on right well to explain it pretty simply this build function now reruns the entire widget tree whenever the value of this user changes so if the value of name changes it will rerun if the value of age changes it will rerun what if you want to do something like this widget tree should only rerun when the value of name changes how can we do that so we want to rerun the entire widget tree when one property of this class changes that's why we use dot dot select method which is present on the user provider or any type of Provider so if you want you can just use the select method over here also so you have user provider.select but we are doing it in the watch method so that we can watch the value for its continued continuous changes right so we want to read a property known as name that means the entire widget tree will only rerun whenever the value of name changes to give your demo I'll remove this user provider or this user class and then I'm just going to have user you can see this is now of the type string so you will remove it from your from here restart the entire app and now whenever you change the value like this you can see both the places it gets the same thing because it's of the type string which means it's a name property and if you change the value of age nothing gets changed even though we have the H property right here so that's why we want to use the Select Property we use it whenever we want to listen for changes in value of one single property from a class you can do the same for age and thus here over here you'll have to put two string and when you restart you have 0 0 if I do something like this nothing gets rebuilt but if I change the value over here it gets changed you might think it's the same thing as having final user is equal to ref dot watch user provider dot name but it's not the same thing because you are watching the user provider so whenever there is any change in the user class be it age or name this will rerun to check it you can just call the print function and have rebuilt aware and you'll get to know this entire function rebates because what we are doing is just accessing the user property and calling the name property on it so basically we are listening to the user class and then accessing the name property on it however in this case we are not watching the user class we are watching user classes one value which is returned over here which is age I hope you get the difference it's not the same thing anyways I'm just going to remove everything and have a very simple user dot h dot name and user.h Back Again sweet so now we have covered three types of providers the next type of provider is the change Notifier provider I'm not going to go deep into the chain node file provider if you want to know more about change nodifier and change nodifier provider I would recommend you to watch my provider video because this chain Notifier class directly comes from riverpod to easily migrate from provider to riverpod because many of the functions in provider have changed Notifier class that's why it's there for easy transition but however in the riverbot documentation it's mentioned that we shouldn't use much of change Notifier provider if you are building our application from scratch it's always recommended to use State Notifier provider so what is the syntax like and I'll show you the difference and I'll tell you why it is encouraged to not use chain nodify provider so we have class user Notifier and I'm just going to add change at the end and then it is going to extend the change note F fire which is not from riverpod it's from flutter SDK itself the material.dot and then we can create the similar functions but in this case here we don't have access to anything like a state or anything which are State Notifier gives instead we have to create that on our own so we love user user is equal to user and 0 and this will be a constant then we have to create the same functions then we can have user user user user same thing exactly same here we are treating user as the state variable here we have done the same thing but instead of having to do or create user variable Steve did that for us now we'll have to go to the main.dot file and of course create something like this here we use State node defy provider to expose State Notifier here we are just going to have user change Notifier provider is equal to change notify provider we have access to ref aware and then we are going to return a class of chain nodifier so if you try to return a string it won't work just like a state Notifier but if you also try to return user Notifier it won't work what you need to return is user Notifier change and now it's done now similar to all of this we are just going to have ref dot read user change Notifier provider user chain Notifier provider and here is the difference here we use dot Notifier so that we could call the functions but in this case we don't have to do that if we remove the dot Notifier it still works so if you do dot aware we have access to all the methods we don't have access to the user right so that would mean if we do user chain Notifier provider here this is of the type user Notifier change because this is exactly like this so we have access to the methods here right like dot update age and all we don't have access to the user model or the state so to say so we'll have to do dot user and then we'll get access to the user and then we restart we have this this and nothing works because this is not like user notify or a state Notifier class instead whenever you want to rebuild the entire UI you have to call Notifier listeners function once you call this function it will notify all of the clients that are listening to it for example ref.watch and tell hey I've got a value a new value and it's been updated please check third world revert now if I do something like this you can see it updates you might think it's the exact same thing right now I just need to put notify listeners here and in every function and it will be the same thing and you're right there is no difference in the point of view from a user but as a programmer you'll see this is mutable I said in the start right we have all the providers immutable which is a good thing but only one provider is mutable others in the start if you remember I said we have all the providers immutable but only one provider is mutable and that provider is change Notifier provider this is immutable that means you can do something like this so if you have like this you can do this that means we can change the value of the user object outside of the class unlike State Notifier provider chain Notifier provider allows that and that's a very bad thing to be honest and that's why riverpod also does not recommend doing this however if you have a provider used project and it's pretty big to convert we have seen Notifier provider and you can use that it's not recommended and I would also recommend you to not do so now after having a brief knowledge of chain note if I have provided the next type of provider is the future provider future provider as the name suggests is a provider based on HTTP calls or asynchronous code even Firebase calls so when this future provider is used for futures so if you have asynchronous code you'll definitely be using future provider and it will make your life much more easier it is kind of a replacement and a shorter code for future Builder and a better one in my opinion I'll show you why I say that and it will be a lot more interesting let's get into the world of future provider but first let's just remove the chain Notifier provider and even State Notifier provider we don't need them anymore I hope you've understood the differences between both of them also I'll remove all of these functions all of this and we are back to what we had started with except still we have consumer widget and we are going to keep using it so now in the main.dot file let's create our first type uh our actually fifth type of provider which is future provider so to give the example of a future provider I'm going to use an external API of course you can use the future inbuilt class to display some values but I think the best way to do it is to give a real life example and that is from this API Json placeholder API this will give us a random user and when we go to this URL so I'm just going to copy this URL and also I've made some changes in the user model because this is the data we get we want to get the name and the email of the user that's why I've created this of course if you want you can add other fields but I'm just going to go over to just for example and then obviously the same thing the future provider we need to create so I'm just going to have final and then I'm going to call this fetch user provider and this will be equal to Future provider similar to all the other providers and obviously this part right here if you hover over this this is of the type null just like all the other providers now what I want to do is I want to get this API so I have to use a plugin like HTTP which I've already installed or you can use do and it should work for you as well do will give you additional features too that will be helpful while using future provider especially like canceling the network requests that you are sending in case the user just goes away from the screen right so anyways what you want to do is send a get request to the URL we have copied so let's just put in the URI over here let's call this the URL and now I want to send the HTTP get request so I'm just going to have import HTTP Dot and we're going to use it as HTTP and then we are going to do http.get and then uri.par so I'm not going to go much into details for this get request I think you already know about it but anyways if you don't know we are just sending a get request so that we get the data back so we are just going to have return http.get you can see this is other type future provider response because get request is having the data type of future response and since you are in the future provider it will ignore this future and it will just return a response encapsulated in a future provider but that's not what I want to do right once I get I do the get request I want to send the user model across so I'm just going to go ahead and use dot then and whenever this HTTP request is done we will get a value and this value is a response this is a short form for await so if you want to do await you'll have to add easync instead of doing that I'll just use dot then I'll get the response and I just want to return user Dot from Json and whatever I get I'm just assuming I'm going to get a successful part I'm not catching the error here because error will be caught somewhere else in our UI file that will be very interesting so we're just going to have value.body past 10. of course if you want you can go ahead and catch any error if you want over here but there's no point of doing so because future provider as I said is a replacement or a better version of future Builder I'll now we'll get to know why if you just come over here you can see future provider is now the type user because we are doing Dot then so whenever http.get is done we'll get the value and we're just converting the value to a user model and we are returning it from this entire function so this is now of the type future provider user so here comes the question now how do I display the user name or user email over here or in the app or whatever for that let's go to our home screen and you might have known by now that we always use ref.watch and we do it for all the providers that we have done till now for provider we did that state provider State notify provider chain Notifier provider everything but if you do ref.watch for a future provider let's see what we get so I'm just going to copy this paste it in here import it and put it as user and you'll see this is now of the type async value user what is this async value you might ask async value is like a better version of async snapshot what is async shop snapshot well if you return something like a future Builder and of course you need to pass in some future I'm just going to pass in I'm not going to pass in anything I'm just going to keep it as it is but here is our async snapshot this async snapshot gives us access to you can see snapshot dot connection State snapshot dot data snapshot dot error and snapshot so you can see we get all of these things and the problem with async snapshot is that the snapshot.data snapshot dot error they're not interconnected with each other so just for doing what we want to do of course I'm not saying we can't do all of these tasks with uh future builder of course you can do it I said it's a replacement so if you just try to do something like that you'll have to do if snapshot dot dot connection state is equal to connection state DOT waiting and after that you'll just return a loading bar and then you'll check if snapshot dot date has data so if the snapshot has data you're going to return your widget tree which means all of this part otherwise there is no data and you are going to return that yeah we didn't get any data and then you're also going to have snapshot dot has error so if it has error then you're going to display the error if it doesn't so async snapshot basically suggests that all of these states are not interlinked with each other they are independent of each other but actually data error and loading are pretty interconnected to each other aren't they so it's not a clean way of doing it in my opinion so async value is a better thing in my opinion async value makes all of these things correct it's cleaner code to write you'll see it's such short code you won't believe it there is proper handling error handling data loading and error feels like they're interconnected to each other you'll know why so now you might think how do I get the value from this async value right well the answer to that is if you just use user now user dot you'll see you'll get many options like user.as data so if you do as data it will give you a valing value of the type async data user but that's not we want we directly want to access the data or the loading or the error part or three of them we want to handle together and for that we have the function dot when and when we do this when you can see we have three required parameters data error and loading for data we'll get a simple data so whenever we get the data what do we want to do if there is an error we'll get error and a start Trace both together and what do we want to do then and if it's loading well if it's loading what do we get nothing really because it's loading we don't want any data and now we just handle all of these states you don't have to write the big future Builder code anymore you just have to write user.win that is basically short for ref.watch.1 thank you it's basically like this so we are watching the future provider and whenever we get any of these so data error or loading it will make this happen and in case the loading shifts from data it dynamically does for us just like future Builder you know so now we can handle the data so in case there is a data what do you want to do well I just want to return a scaffold very simple but what do we do in case of error well in case of error let's just simply display our error in the middle of the screen so we have error.2 string and for loading we are just going to return again A Center widget with a child of circular progress indicator and there we have it with just simple line we have solved the future Builder Big boilerplate code problem and we have handled all of the states correctly as well and here it's giving us an error because you have not returned anything you'll say we have returned from data error and loading that's right but we have not returned this entire future Builder thing uh sorry it's not future Builder but replacement for future Builder basically so now you can have return over here and all of your problems fixed now if I just restart the app you can see we are getting this loading bar and then we are getting the screen now to display the data if you come over here this is of the type user so to display it correctly all you need to do is user dot not user sorry data dot name and remove the constant from here now restart the app and you see the name showing up and that's the exact name that's over here so we have successfully got the data if you're wondering why on restarting the app we get this loading indicator the reason for that is we have returned this entire scaffold in the data but we have not returned the entire scaffold in case of a circular progress indicator or a centered text so if you want to get a white screen you can just wrap these widgets with a scaffold now I want to show you the process of error handling so if I by mistake I mistype it so if I just do users which is another API of its own so if I just go to users over here you'll notice it gives us a list of all the users so if I do this and do this it won't work because it's giving me a list of user earlier it gave me a map of all the user so I could directly use user Dot from Json but in case of all the users which are in a list I have to do a for each Loop right I've not done that so it should likely give me an error so I'll just restart the app and here you can see we are getting this error it's not properly visible because you have not wrapped it with scaffold if you want you can wrap it with scaffold to see it properly after you do that come over here and you'll see type list of dynamic is not a sub type of type map string dynamic as I said these things that this value dot body is of the type map but it's actually a list and that's why we get this error so we have the proper error handling done as well there are a few more properties over here so if you just do ref dot watch fetch user provider Dot and then you check there aren't more properties like if you want to check if it has error or not if it has value or not if it has if it is loading if it is refreshing if it is reloading then there's when and whenever data so if you don't want to handle all of these states like error and loading you'll just do when data so whenever you get the data this whatever you pass over here will rebuild so these were all the important functions another important function if you want is dot map over here so if you do dot map it's similar to dot when you'll get all these functions but now the value will be of the type async value so your like we had the value of async value here we have all of these values like async value so if you just hover over this you get no sorry not async value async data and then you'll get user so if you want to access the user value in it you can do data dot value and it will give you access to the name uh to the user model and then you can call Dot name dot email properties on it now after having this future provider let's talk about this provider ref I know we would I told you I would talk about it early on but let's talk about it now so generally when you have this kind of HTTP requests you won't be directly writing this in a future provider instead what you'll be doing is writing this in a separate class of its own so you'll have something like class user repository or something let's just call it a user repository and in here you will be using the http called so if you are here you're just going to write this entire code in a function so you're just going to have future user fetch user data and then you're just going to have your calls right here and obviously the HTTP part and then you'll be using something like user repository dot fetch user data and obviously you'll have to return something from your otherwise your future provider will be of the type null so after doing this you might think that yeah the job is done but generally all of these repository classes and all of the classes that you have are provided so a provider is used for them why a provider because suppose you have a lot of things to be taking in from the Constructor so for example you are testing your code so if you're familiar with guest testing you might know that all of the dependencies are taken in from the Constructor and then in the testing screen you'll mock it if you don't then that's how it's done and if it doesn't make sense don't worry about it but generally dependencies like Firebase if you're using it's taken in from the Constructor if you're using HTTP an HTTP client is taken from the Constructor and so on then a provider is created out of that so you have user repository provider which will be equal to provider ref and then user repository classes return now if there are there is a Constructor there will be multiple parameters to pass in and you can pass it right here in the provider itself the reason for that is I said they are going to be dependencies you can pass dependencies from here and if it doesn't make sense like why would anyone do that you can check out my testing video which will be out soon but that's how generally it's done so if there are like five to six things taken in from the Constructor and you want to use user repository suppose in a 20 or 30 providers that will be very difficult right just using this class and instantiating it every single time is just a waste of time for us so instead a user repository provider is created or a provider is used for them these classes in our case there is nothing like that because we are not testing but it's generally done that way another reason to use provider can be because provider will cache it and return its instance pretty quickly otherwise we'll have to keep creating the object of this user repository class again and again which will be causing memory issues instead if we just use this line it will cache it for us because provider just caches stuff whatever we pass it in and will provide it to us thus not increasing our memory space so now what do we do well I'm not going to use user repository class now instead what I'm going to do is grab an instance of this user repository class sub user repository suppose like this which will be equal to ref dot watch now you might get confused that ref.read should generally be used right because this is not a build function and I said ref.watch should be used outside the build function a rev.watch should be used only inside the build function not outside outside is ref.read and even in functions it's a ref dot read and this is a function right but those things aren't applied here of course I'm not saying you can't use a ref dot read you can use it the reason for not using it over here and even in the build function is that if the value of this future of this provider changes for now it's a provider so its value won't change but what if it's a state Notifier provider that we are dependent on the syntax I'm showing you is accessible for all the type of providers so you can access a provider State provider State Notifier provider chain notify provider and if you want a future provider itself and of course the syntax that I showed you earlier of using rev dot watch if you don't want anything value dot when and whatever but that's how we do it if you do read it it will just take in a one-time value and then think yeah this is it and it will not continuously listen so if the state provide a state Notifier provider value changes it will be bad because we won't get the updated future provider if we use ref.watch instead if the value changes this future provider will rerun and notify all of our clients for example this home screen and tell them yeah the value has changed so please help us me out right here just to rebuild my widget tree and it will rebuild so I hope that was clear now I just want to use ref.watch user repository provider and that is why this provider have helped us this provider ref allowed us to talk from a provider to another provider widget ref allowed us to talk from widget to a provider and now of course you have access to the user repository class so you can just call return user repository dot fetch user data and you're done if you just restart your app you can see the name shows up correctly and all is well so I'm going to keep the future provider here just as a reference to steam provider and other properties that are available which I want to show you after we complete the sixth and the final type of provider in flutter ever part package which is the stream provider so let me type it right here to create it we already know we're just going to have final some stream so you can name whatever you want I can't think of any name so I'm just going to ask stream provider miraf and then we have it like this now obviously we need to return a stream but since I don't have any stream apis in my mind correctly currently what I'm going to do is use async star which will allow me to return whatever values that I'm returning from your as a stream and to do that I'm going to use the yield keyword and after that I can return any value but since this is a stream I think it makes much more sense to use changing values so I'm just going to do this of course if you're not me you can use a for Loop instead of typing all of these tasks but anyway after having this done you have a stream provider ready if you have some Firebase calls like you can do something like Firebase Firebase firestore dot collection and then the name of the collection suppose as users dot document user ID dot snapshots and that will give you access to stream and then you can return it right here but since I don't have Firebase files to plug in anything done I'm not using that but I've already covered it in some of my builds you can check them out link will be mentioned in the description so anyways we have it right here which is good the thing to note is after adding async star you can yield and it will give you all the possible values like you can return the possible values which will keep changing it will keep returning it so after having this um I'm just going to go to the home screen and now I'm just going to comment all of these lines I'm commenting it I'm not deleting because I want to give some major features on future provider and stream provider that are left all right so now you can do return of course the Syntax for stream provider is very very similar or exactly the same like future provider so all you need to do is ref dot watch after doing this type the name so mine is stream provider Dot when this also is the type of gives the type of async value and now you get the data you can handle that error you can handle that and it will also give you stack trace and loading so you can handle that as well loading and all of those tasks are pretty similar so I'm just going to copy paste them so after having all of this the last thing that I need is data and what am I going to do well you can see it's a list of int that I'm returning so you can either use list view Builder or whatever I can just use return text Data dot to string so that it displays a a text with a list correctly so I'm just going to restart and here you can see I get all of this the reason for that again I'm not putting a scaffold you always want to do that and in case you're wondering if I have to do it for all of these scaffolds why shouldn't I just put it outside and you're absolutely right you can do it so you can just do returns scaffold all right and then in the body you can have all of this task done so now you don't need to add any scaffold over here because your parent widget is now a scaffold so it's not required here as well and now for the loading part you will also see there's no black screen coming I'll just restart and there is no delay but you can see a list is right here I hope you can see it so this was it about the stream Builder if you have any stream values which is going to change you can keep doing it so if you have 11 and 12 restarted and you'll see 11 12 right here great so this was about stream Builder again it has the same properties like future Builder like has data Hazard or is loading and all of that stuff I'm not going to dive into it again you can check them out for yourself there's map method when data when or null whatever so after getting all of that done what are the key features that I wanted to note before noting them I want to say that this ref is available on every provider right so you can communicate with all the providers that you want so if you again want to do this user repository task and return it you're good to go now what are the features that are available to us and it's not just for future provider or stream provider it's available on every single provider keep it in mind it's available on every single provider but it's generally used more with future provider stream provider and state provider State Notifier provider all of them not with a single provider what am I talking about well it's the modifiers modifiers mean if you just come to this future provider I told you you can add generics but other thing that you can add over here is dot family with family what happens is suppose I have this future provider but I want to modify this function a little bit I want to get this user value based on the user input so I'm just going to have int input and I can take this pass it in and do the string interpolation this is not a string anymore this is variable URL all right now I have the user input so whatever the user types we want to get that user's data so if I have this API and I do user slash 5 it will get me a different person so I want to do exactly that now how am I going to do that well you can see it here it asks for the missing argument if I type in one it gets satisfied but this is still not the user end call user input is what is entered on a different screen altogether it's right here so I'm just going to comment the stream provider for now we have this provider now and we are going to have suppose a text feel over here which will tell us what user value we want to get in the UI file now uh you'll have the user input but for that you'll have to declare something that we will show to the user initially right and for that we are going to create an end variable but doing it in a con in a consumer widget which is basically an upgrade over stateless widget is not quite possible I want to use such State now so I'm just going to use stateful consumer so I'm just going to use the stateful consumer widget and I'm going to have my home page I'm going to return everything from here I'll return this class now and now changing it to a stateful consumer widget is now giving me access to create a pay suppose the user number variable which is initially one because I want to get the first user's data but in case the user decides to just change the value which we want to get of the user we'll have on submitted value and then I can just do such State user number is equal to whatever value the user gives and obviously parse it say we have n dot parse actually we don't have to pass it because this is going to be of the type string not integer because we can't pass in an integer in a string right I mean at the end of the day it's just going to get converted to a string but anyways this is fine this will also be a string and this will be like this all right so now after doing this set State usually such state is not used when riverpod is used but I'm just giving a demonstration because I just don't want to dive right into the clean code part I'm just explaining it so what happens is whenever the user gives a new value I want this build function to rerun and whenever this build function reruns I want to give the particular provider the value so I want to give the user number variable to this provider because here I want the same thing I want to get access to what the user has typed and that's why we use the modifier dot family when we use family in the parameter year we can have a value taken in so we have string and that can be the input and then you can pass that input right here so this as I said is like a function correct so in the function I have another input and getting that I have access to this over here now this throws an error in the home screen to resolve it what you need to do is you have the switch user provider you just need to add a function like this and pass in the user number simple so we have done ref dot watch the user provider provider then you've treated it as a function and in the function you've passed in the user number if you remove this family you don't have to pass that in right now let's see it an action so if the user initially it's one so it's showing us this name but if we do 5 and enter you can see this entire rebuild and we have Chelsea twitch sorry if I pronounce it wrong showing up if I do 10 this shows up of course this is not ideal that's why fetch state is not generally used you can use some other value but I just wanted to point that out that you can do this another thing that I want to point out is this family has a limitation right here you can't have two inputs like this so if you want to have int a you cannot have two of them you can only have a single thing taken in from the argument over here or you can just pass in a single thing from here you can't pass in two things so that's one limitation and we're going to see a solution for that but that will include using a new package if you don't want to use that in your application you can obviously use some other types so for example if you want you can use a package known as Tuple you can use that and you can provide values it will give you Tuple two Tuple three two pill four all of that so you can convert that into a single data type and pass it to this parameter which will allow you to send in four or five values together encapsulated in one single data type another one of them is using a class so you can just directly use a class and pass it in but make sure that if you pass in a class the class should be immutable meaning the class that we have right here is allowed but you can't have a class that's immutable meaning you can change the state of the class we can't do that in our example because it's immutable and you can pass in primitive data types but you can't pass in a non-primitive data type from here if you want to pass that in you'll have to override their hash code which is this or the is equal to equal to operator only then can you pass it in but there is a problem with this line now the thing you're doing is taking an input from this home screen from this text field to be very particular and passing it in over here now there are times that this input doesn't change but there are times when the input can be changed but it's never reused so in that case we have something known as Auto dispose which is another modifier we have access to and you can use both of them together or you can just use Auto dispose if you don't want a parameter that a function depends on so you can just use this like this or you can just use family and auto dispose together so when you do that it will avoid memory leaks in your application and it will auto dispose your provider with no memory leak and it will will of of course dispose of your provider it will destroy your provider's data and state whenever it's not in use that's why Auto so automatically it will dispose it off and you can do the same thing for every provider so if you have provider State provider State Notifier and state Notifier provider change notify provide a future provider and stream provider I also mentioned State Notifier but there's no Auto dispose for State Notifier obviously but State Notifier provides us with one thing that I forgot to show it to you The Witches if you extend State node a fire of course you have to do user repository I hope this is refreshing to your memory and then you'll have super and then you can do state right and this state can be a Boolean value for example I'll just consider it that this Boolean value is is loading just for now and now you can have one method in the state Notifier called dispose whenever you extend a state Notifier you get access to dispose and you can dispose of whatever you need so if you have a stream running in this user repository class you can just cancel the stream subscription so you can just call whatever stream there's dot cancel or otherwise if you have text input field which is generally not used in repository but in controllers so if you have access to text field repository and stuff like that like final text field text field no text controller controller which is equal to text editing controller you can just use controller dot dispose and you can dispose it off that's what this dispose is used for but anyways coming back to the original part and coming over here it will auto dispose it off and it's generally recommended to do for all of these providers unless there is a real use case for that if you don't want to dispose it off you want to keep the values constant you can do that so the same applies for stream provider if you want you can have family you can have Auto dispose or both together and the same applies for our provider idea so you can have provider dot family or provider.autodespost we'll just use Auto dispose now if I restart my app here we have it seems good it will auto dispose it off whenever it's not in use so if we change the screen it will dispose it off so now we are done with all the type of providers we have had six providers to look at to give you a refresh of that provider is a read-only object so if you want to provide a value be it primitive data types like integer Boolean string you can use them or non-primitive data type like list map whatever or even instances of classes I've already mentioned the reason why second state provider if you it is like an upgrade of the normal provider if you just want to update a simple State like an integer value or a Boolean value you can do that and just to get your minds more open to this instead of using this user number what you could have done is just used a very simple State provider because all we want is a single string right so instead of using family what we could have done is use a state provider got the value over here and updated it whenever the User submitted the text fee but since I wanted to show you the family feature we could have done that but if you want go ahead and try it on your own it should be fun for you second is the third one is State Notifier provider this is generally used when there are more complex state to be dealt with for example the user class and we want to modify their properties or whatever fourth one is chain Notifier provider it's recommended not to use by riverpod it's just for transition from provider to riverpod if you have bigger code base this will help you but if you're starting from scratch or you have a smaller project I would recommend you to not use it because of its mutable state fifth one is the future provider so if you have asynchronous code and you want to avoid the Roth of this future Builder and async snapshot you can use future provider sixth one and the final one is stream provider so if you have a stream and of course you want to get rid of the stream Builder and async snapshot again you can use stream provider it is reusable and with and it should help you a lot all right now after knowing all of the providers there are some methods on ref that I want to talk about so we saw the different types of refs the first one is the widget ref s us to talk from a provider from a widget to a provider second one is the provider ref which allows us to talk from a provider to another provider and the third one which we've not talked about is a simple ref so what is this ref well ref can be considered like a super class to this provider F and widget ref for example if you have this user repository class and your user repository class needs access to ref generally as I said repository classes don't contain such logic it's just for business logic but however if you by chance need it or any of your classes need that you'll have refused here this ref will allow you to talk with other providers so if you have ref.watch similar methods like not even similar is the same method so you can use ref away and then you can communicate with all the providers that you need so for example if you need a stream value you can use fetch user provider because these providers provide value not just widgets it can provide a value to any classes any functions anything that you want so you can have user repository here and then just have this Dot pref and now you have to pass it in so what do you pass a 10 well just a simple ref so you can just pass in a ref over here which we got from this parameter you can just pass it in and this allows you to have ref dot watch ref.read and all the ref methods that we have access to now after knowing this much we can come back here there are other ref methods as well so the first method that we are going to talk about is ref dot keep alive so we have ref dot keep alive after using this basically whenever we use Auto dispose this method gets activated however if you don't have this method so I'll just remove this you can see dot keep alive method is no more on it because that's what its use case is whenever you dispose of so when you transition from one screen to another or you or the future provider is just not in use and you want to preserve the state of this future provider you can use ref.keeper live so that will make sure that the state of this provider is there even after it is disposed right second one is on this pose so whenever a dispose is called what do you want to do and this on dispose method is available even if Auto dispose is not there so it's available and if you have it then also it doesn't matter so whenever your provider is disposed what do you want to do so in case of this pose you want to make sure that suppose you have the HTTP client example for your you can just do http.client.dispose or if you have text editing controller you can dispose it off or whatever needs to dispose of so if you are in a stream provider you can use that over here as well so I'm just doing it for both of them and whatever methods I'm telling you is available on all the providers that we're talking about okay I'm just giving you an example of showing it by on one provider so whenever on this pose is called you can just do well whatever you want to do so if you have a stream subscription going on here you can cancel it it will get canceled by Auto dispose I guess but if you want to dispose something else you can use that then you have access to on cancel so you have ref dot on cancel on cancel is used whenever your provider goes into a post state that means it's no longer being used for a certain while or it gets disposed that means it's no longer being used anytime so that time that or on cancel gets run so it's for both the cases temporarily pausing and all time pausing or forever pausing whatever you prefer and then there's ref dot on resume so whenever your providers get resumed what you want to do you can just type uh you can just pass it over here in this function right here that means your provider was in a post State and it starts to rerun again so after it was going into the cancel State and when it comes back it comes back to the on resume state so these are kind of like life cycles of this ref which you can get access to and do your work but generally I don't think for a smaller app you'll ever need this and the final function is on remove listener or the on ad listener so whenever a listener is added to the stream provider or the future provider you'll use this so these are the very important methods the last thing that I want to talk about in this flutter riverpod package is something known as a provider Observer now I told you if there are Global variables it would be very difficult to understand where the provider is being added where it's being removed where it's being listened so it is quite a task but with access to this something known as a provider Observer you can log these things out so I'm just going to go in the lib folder create something like a logger riverpod.dot file then I'm going to call this logger riverpod and then we need to extend to something known as a provider Observer so after we do this we will get access to something known as an override method which is called voided update provider and it gives us access to all of these things so there is provider base which is like a base class for all the providers so if you just go to this future provider you can see it extends the future provider base and future provider base extends the provider base so this is like the parent class for all the providers then there's the previous value so what was the previous value of our provider then what is the new value of the providers and then the provider container provider container is what is used within the provider scope provide a scope is made of this provider container you can see it provide a container and it's used at a lower level and now if you want you can print all of these things out so you can print all of these values now just restart your app open up your terminal and to make this logger work what we need to do is go to this provide a scope and in here we have a bunch of more properties than just a child so we have overrides observers and parent you might know where to put it in the Observer because it accepts a type of Provider Observer so we can just have Observers pass in a logger River pod and this is not a constant anymore so let's remove it and constant is just my app now if I restart the app you can see when the future provider came up we have Auto disposed future provider which is the provider base then we have the previous value which was the loading value right so whenever we launch our future provider first there is loading because it's fetching the data and then when it gets its value it gets async data user value and the user value is written right here and we have a container instance of Provider container now if I just change it so if I write 10 you can see it again ran it gives us this value it's pretty good to debug with this if you want to know where or what provider changed and how it changed all of those things there are more overrides like this so the next override is at the rate override void dead add provider so this is done whenever the provider is initialized it just requires provider the value the initial value and the provider container and similarly we have for other rate override void did dispose provider so whenever obviously a provider is disposed you'll get values where we won't even get access to Value because it's getting disposed what's the purpose of getting the value we just get the provider base which provider is getting done and the container you can obviously add print for all of them but these are the three overrides that you can have while after you extend a provider Observer and let provide a scope know that we are observing all of this if you want to go ahead and try it out try it out print it out and see the output for yourself it's pretty amazing it will help you in bigger application there are multiple more functions that are very useful while testing so you have provide a scope and there you have the overrides property so if you want to override a certain provider with a certain value for example stream provider you can do override with value and provide a new value to it so you have passed in the new value in the form of the Stream So if you want a stream of list of all of this you need to pass it in and you can override it and it will help you in testing if you're familiar with testing you might know why if you're not don't worry about it this might also help you so this was it for the entire flutter riverpod package I've explained to you about all about providers the widget refs but that's not all it we have not done with the tutorial yet that is the main thing left after having the knowledge of riverpod let's discuss some of the disadvantages of riverpod first you might notice that there are so many providers there are six providers for us to choose from it can be confusing and difficult to choose which one to use second disadvantage is that over here in our home screen we're using consumer stateful widget instead of stateful widget and in stateless widget we are using consumer widget using this is quite a task because converting it into a stateful widget and then converting it to a consumer stateful widget that is a bit of a task third disadvantage is enough providers we are when we use family I told you we cannot have more than one type of parameter what if I want to get a input of 3 or 4 I told you you can use e Tuple or anything like that but do you think it it would be more convenient if we had access to a way which would allow us to add more and more parameters and also if there were more parameters we could use named parameters so instead of having positional parameter we could have named parameters just like we have for functions and classes so these are the basic disadvantages of Riverport now what are the solutions to it well there are solutions to a few of them for so many providers we have a package that we are going to look at which is called riverpod generator along with riverpod annotation we're going to dive deep into it but for a basic level that's what we are going to use converting to a stateless or a stateful widget over here we have an extension nvs code called riverpod Snippets you can install that and after you install that you get access to something like this so if you just type State full and it will give you access to stateful Consumer so now you can just create home screen like this and all the boilerplate code is generated if you want a stateless widget which is consumer stateless widget so you'll just have stateless consumer and you get access to it if you want to create a provider you can just type provider and all of those is done so I can just type simple provider give it a type if you don't want to give it a type remove it and then we need to return a simple value and the same goes for all the type of Provider be it future provider stream provider or state provider or even State Notifier and state node F5 provider so this is a handy snippet for us the third is the family part so having more than one parameter well here is the cool part the package that we are going to use in our Port generator and whatever pod annotation will allow us to add multiple uh inputs multiple parameters for our family so we're going to take a deep look into it and let's get started now to get started go to your pop spec.aml file and add riverpod annotation package in dependencies and in the dev dependencies add build Runner package this build Runner will give access to code generators and riverpod Generator package which will allow us to generate trevopod files and classes this riverpod annotation will give us access to at the rate riverpod which we will see right now so now if we come over here let's try to replace this future Provider by writing with The riverpod annotation package so what are we going to do well we have first of all at the raid River pod all right now after having this we will click on enter you can see we have imported riverpod annotation package after that just we need to write our simple function just like we write it a very simple function but it should be globally present just like a providers so here we will have future because that's the return data type of this fetch user data function future user so we are just going to have that and we are going to call this fetch user you don't have to write provider after this because you'll see later on that the name of a provider is going to be fetch user provider we just need to write fetch user and then create the function now in the function obviously we are going to have these two lines passed in because that's what we want to do and we'll comment this out we don't need this provider now in this parameter here we will have access to something known as fetch user ref ref now this won't make sense but when we do something you'll understand why we are doing it and what we are doing and then we want the string input so we are basically getting access to ref just like we did over here and the input just like we did over here and you can see we are getting this error but we shouldn't worry about that now what we want to do is add a line over here called part and in this part we need to write main dot g dot dot so basically you'll write the name of the file and in between you'll add dot g now I know I know this is not making much sense to you but so now what you need to do is dot run build Runner and then add watch so after doing this you're continuously watching for any changes in the file and you can see after it succeeds all of our errors disappear so how is this suddenly happening and how do we have access to something known as fetch user ref the answer to that will be found in main.g.file which is automatically generated these are what are called code generators after running this build Runner this file automatically generated and it says do not modify by hand and it's a part of main.dot file so we don't have to import main.g dot dot file anywhere we just have to import this file just like we do for our providers but it will automatically get the stuff that is passed in in this file and what do we have in this file well you can see fetch user provider class which extends Auto dispose future provider so it automatically got to know that yeah this is of the type feature I want to give it of fetch user provider which is of the return data type future user provider you can see it and we also have access to fetch user F which is auto dispose future provider F so basically what it has done is created this line and we just had to write a simple intuitive function and that's how useful these functions are all you need to do is add The riverpod annotation create a function and you get it now in the home screen also you can see nothing changed because as I said we all only need to write fetch user and it will create a provider based on fetch user provider so I hope that was very clear now let's try to do the same thing of course if you want you can compare the syntax this is much more intuitive because it's a function now let's go to the user.dot file and we have our user repository provider let's try to write a code for the same so we are going to have well user repository return then we are going to name it so we are going to name it user repository and then give something known as user repository ref and then we want nothing else so we'll just have this done then we are going to return the user repository and pass interest all right now what we need to do is go up at the top and add a part user dot g dot dot make sure to add this otherwise it won't work for you and the reason it's not getting Auto generated as I said if you don't add at the rate River pod annotation it won't work so just add at the rate riverpod and then save it and as you can see it took a bit of time and it generated user.g dot dot file and it just works you can see when we do user repository we watched user repository provider it all works now the last thing that I want to show you is the family tag so for the family I told you we can't have more than one input but here you can see this is a simple function right so we can have more than two three four you know parameters as many as you want so here I'm just going to take an end some value then Boolean second value just for you know seeing that what we get in the reference so now after I do this the main dot g dot dot also updates and when you go over there you can see fetch user provider now has some value and second value so when you go to the home screen it can you can see we need to add three additional arguments now so we need to pass one and falls over here only then will our code run however when we have more than two or three kind of you know parameters we generally use named constr or named parameters so now we can just wrap them like this and have required required and if you want you can make this nullable but I also want this required so after you do this this fetch user ref should always be non-required so that means it is a portion positional argument but all of this are named arguments now now you can come over here and here you need to pass in the named parameters that are required so this should be input then this should be some value and this should be second value after you do that you can see all of the errors disappear and we get nice little multiple family things and it's much more cleaner isn't it because more having more than two inputs always requires us to not get confused and add the named parameters so this was it about Riverport generator but I can't show you more example because the only two types of Provider that are supported till now are future provider and the normal provider State provider State Notifier provider chain Notifier provider and stream provider are not yet supported however for State provider and state Notifier provider there are some Replacements but I'm not going to look at them in this tutorial if you want to know more about them let me know in the comment section and I'll create a separate video on them but there are many benefits that you saw and it solves most of our problems and soon I think most of these providers are going to get supported also another thing that I forgot to point out is that if you go in any of this you'll see auto dispose future provider so it automatically adds the dot Auto dispose for us and that's very convenient because many of the times even I forget to add it to my providers so it's a really cool feature of course if you want to keep the state alive you can use ref dot keep alive and all of that stuff and you can use both of them and whenever you use riverpod annotation or riverpod generator it's not necessary that you always use this other data report and create a function out of this you can also create a normal provider and it would just work fine for you as you saw this is much more intuitive this was it for the tutorial if you're interested in building projects with robot 2.0 check out these projects on the screen thank you so much for watching and I'll see you in the next video
Info
Channel: Rivaan Ranawat
Views: 63,629
Rating: undefined out of 5
Keywords:
Id: pwflXIA-6YQ
Channel Id: undefined
Length: 114min 32sec (6872 seconds)
Published: Sun Nov 13 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.