Flutter State Management - Basics of the Provider Package

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
welcome back in this video we will be starting a brand new section called state management now i've done state management before in videos or previous videos of mine for example we've looked at stateless widgets versus stateful widgets and then as part of the state full widgets there's a state object where we can actually set the state using the set state method or the set state function so what is this section then about if i say this is state management now so we will look at an example today and see why maybe using set state all of the time will not be a hundred percent effective in fact most of the time and i mean 99 of the time you will not be using set state so just hold on there we will get to that example now so if you go to flutter.dev docs development then on the left hand side you will see this data and backend state management and you can go through the introduction think declaratively and so forth and at the end we will stand still at options so if you go to think declaratively you will see that it says if you're coming to flutter from an imperative framework such as android or ios you need to start thinking about app development from a new perspective and then they say flatter is declarative and this means that flutter builds its user interface to reflect the current state of your app and when the state of your app changes for example the user flips a switch on the settings screen you change the state and that triggers a redraw of the user interface and we've seen that by using set state there's no imperative changing of the ui itself which means you can't go and say go to that specific widget and just set the text you change the state and by changing the state the ui rebuilds from scratch and we've seen that with the state full widget where it rebuilds the nearest build method and then you can read a bit more about that and the declarative style of ui programming has many benefits remarkably there's only one code path for any state of the ui you describe what the ui looked like for any given state once and that's it so this is quite nice and if you want to read a bit more you can you can read a bit more about how flutter actually handles state so if you want to know more you can go through this state management and read through all of these that they give you which will give you a clear indication of how state works in flutter and how the ui gets redrawn so if we go then to options there you will see and this is quite funny they say estate management is a complex topic if you feel that some of your questions haven't been answered or that the approach described on these pages is not viable for your use cases you are probably right okay so there's different state management approaches they give you a quick general overview and then they say provider is the recommended approach recommended by the flatter team now a provider wasn't created by the flutter team provider was created by a person called remy so right back in 2018 somewhere remy actually created this provider package and quite nice package to use so this is the one we will eventually look at in the end of this video but you will also see set state as one way of handling the state there's also inherited widget and inherited model and you can see the set state is a low-level approach to use for widget-specific state and then this is also a low-level approach used to communicate between ancestors and so forth and this is in fact what the provider package and many other approaches use under the hood so for example provider is making use of inherited widget in order to do what it needs to do so we'll look at that later on but you can see set state is one of the options then we've got inherited widget and the model we've got redux we've got fish redux we've got block rx we've got get it we've got mobx flatter commands binder getx and riverbot so there's a lot of different state management approaches and the question then can be but which one should i use and that's exactly what they say here if you find that a specific approach on these pages not valid viable for your use case you are probably right so luckily the flutter developer community is always looking at other ways to handle state but these packages that we have here some of them is quite good and the reason why i'm choosing provider is because it's a recommended approach so you could have gone with block blocks or redux or whatever it doesn't matter you will get your state managed and quite well so the main question for this video is then why can we not just use set state and i'm going to show you now an example of why we cannot just use set state and where we will start running into trouble so i want you to go to dartpad and if you go to or not to dot bad just go to http forward slash bit.ly forward slash state starter if you open up that one you will get to this page this is a dart pad and if you you can actually run it from here but don't run it from here i want you to go and create a new project folder or a new project a new flatter project and then just add this coding everything in here you can just copy and go and paste it inside of visual studio code right so back in visual studio code you can see i've basically just in my main. i've pasted this coding from that dot pad and if you run this you will see this is the screen that we get so we get data here at the top we've got data here and we've got a button that says change data but nothing is doing anything at this stage i've added a few levels into my appian you can see it's my app it's a stateless widget then there's main page which is a stateless widget there's screen 2 which is a stateless widget there's screen screen23 that's a stateless widget and there's screen4 that's a stateless widget so from the main page i have a scaffold i have an ad bar that says the text data here so that you can see it and then in the body i open up screen two so i'm using the widget called screen two it's not a new screen but it's just another widget but the widget then opens up and it's got a container that will just contain screen three so you can see it's not really anything happening in it i try to explain a concept here and then screen three is a stateless widget again that opens up screen four screen four is a stateless widget again that will just display data here and that's what we see here and we can also see a text widget that says change data inside of the elevated button so it's this one now this is very simple but just remember that normally when you're creating or extracting widgets like we are doing here these classes screen 2 screen 3 screen 4 should actually now be in their own folder maybe called pages and we should have or maybe widgets maybe have a file called widgets and we can place all our widgets that we extracted in a separate file or one widget per file it's up to you how you want to do that which means that normally we won't see the following we won't see a main page in the same file we will have another screen or another page we won't see another one and another one again these will normally be in their own files so just to demonstrate the concept that i want to bring over we need to have all of these in the same file not that i'm going to declare any global variables to be used in all of them we will not do that so we will take it as if they are in their own files but it's just easier to see if we have everything in one file so i hope you get the idea now let's just have one scenario here let's say for example the data that's displayed here that says data here at the top i also want to have displayed d i could do that with a global variable but let's leave out the global variable for now to just demonstrate something here so for example if i wanted to have the data that is here maybe have a variable for it so i will have a final string let's call it data and i will just say john rambo as you can see i like that guys bullets never runs out okay so there's string data john rambo and i want to show the data now yeah so that's easy to do i will just pass in data and if i save it i will see well john rambo will be shown at the top now let's say i want to show this exact same data that's at the top that's declared as john rambo i want to also show it all the way down inside of this text widget there okay so at this stage if i do not declare a global variable i cannot show the data there because it doesn't pick up the data that variable is contained inside of this class so for me to get the data from this class called main page all the way down to screen number four and you will see my widget tree now starts with right at the top the my app which contains a material app then down the widget tree goes to main page which is this one from main page there's a scaffold and there's a screen 2 again which is another widget from screen 2 the widget 3 goes down to screen 3. from screen 3 the widget 3 goes down again to screen number four and so it traverses down the tree so in order for me to actually get the data that we have inside of this class called main page and remember now imagine these are all in different files okay so to get the data from this class main page all the way down to screen number four i will need to pass it down the line which means i will need to go to screen two and i can declare that final variable there again let's say string data again just keep it the same name i will use it in the constructor as a required argument and it will be the start data okay so what i can do then is use that data that we just declared in the constructor and pass in data which is john rambo so now that data gets passed to screen two now in screen two we've got access to it but now you can see that we need to pass it again to screen number three so i'm going to do the same thing again i'll have final string data exactly the same thing again let's have this required and will say this dot data and now in screen 3d i can also just pass the data okay so now we've passed the data from the john rambo to this text widget that one there but we've passed it through to screen two screen two passed it through to screen three now screen three also needs to pass it through to screen four so i can say final string data now let's go to the constructor there and just use the required keyword there again this dot data and for screen three or four i can then also pass through the data from screen 3 and now at long last we have it in screen 4 and i can then have data displayed there and now you can see john rambo and john rambo now to send through the data between different branches of your tree going all the way down until it gets to where you actually want to display it feels very very repetitive and the main thing that we can see here is that screen 2 actually has nothing to do with this data screen 3 has nothing to do with the data it's just passing it through so it works like a middleman sending through data so this is actually defeating the single responsibility principle because screen 2 has got nothing to do with this data being passed through even screen 3 has got nothing to do with the data that that gets passed through it's just acting like a middleman okay now let's look at something else let's say that by clicking this button now if you look at the button it's the elevated button right down at screen number four and let's say in this on-press now i want to actually change the data of this john rambo to something else which means i will need to go back to this variable to change its state how on earth will we be able to do that okay so let me show you this this is also possible so i can i can call set state here try calling set state won't work and why is that because we are using a state list widget so i'm just going to use control dot there and i'm going to convert this to a state full widget and now you can see the data is it in the top screen so referring to it is widget.data so now i'm able to call setstate so i can call setstate in here but what on earth will i be passing in here what will i be setting the state to because i can't set it to that data variable i mean i can go to widget dot data and i can try and set it to something let's say and you can see that's not that's not allowed so we can't do that that data that's been passed through i can't set the value to that data it's impossible and also how is it going to traverse back up the tree in order to get to the part where i actually need to update it so that my abbas text will also update if i click on change data so if i click on change data john rambo must update as well as john rambo there at the top must be the same value so how on earth will we do that okay so for now i'm going to remove the set state here and what we need to do or what we can do it's not not the best way of doing this but what we can do is to make this one at the top also a stateful widget and then this stateful widget at the top we will have a method here or a function so we're going to call this function void change value and what we want to do is to pass in a string data let's say data changed and then what we want to do is call setstate and i can call setstate because i'm inside of a stateful widget i can then call setstate and whatever this data variable that was passed through we can set our data to this data changed and you can already see that we've gone we're going to get a problem here because this was declared as final so we cannot have that one as final anymore okay so it's going to be variable we're going to change it so we can call this function change value pass in data changed which will be the new value that we want to be displayed there and there and then set this data now to that data changed so now the question is how on earth do i call this function so at the end we will actually need to send through this function so that at the end screen number four can use that function so we can send back the data to the top okay so let's see how we can do that so we need to send it to screen number two first then to screen three and then to screen four so we need to traverse the tree exactly the same way as we did with this data variable okay so what we need to do is to go to the constructor of screen number two and we'll have a final function that can accept a string value and let's call it so this one we called change value let's just call this one change data okay so it's a function called change data that will be able to accept a string because that's exactly what we have here it's a function called change uh well in this case change value but the name doesn't matter change data but the functions type must be able to accept a string so that's exactly this function that we are basically declaring there and then we can go into the constructor and we can pass through that function so it's going to be this dot change data and you can see everything's fine and now in screen 2 where we've got that change data we just need to pass in a function that will be able to accept a string value okay so it's exactly that one and we just indicate the name change value okay so that's how we pass it through so now i'm passing through this method or this function into that property called changedata and now we have it so now here we can actually change that data now and it will call setstate and it will change it or update it and this we call a callback so i'm passing through a function and then when it's used this side it's creating a callback back to this one okay so let's go down now screen two has got it but again we can see that screen two has got nothing to do with this data and already we've passed through two pieces of data that it actually need to know nothing off it's just being a middleman to actually distribute this data not good at all okay so let's go to this one and do the same so it's again going to be a function that accepts a string and we're going to call it let's call it change data also and again as part of the constructor we will have required this dot change data so now we can also pass it through to screen number three so that change data we will pass through change data okay so now that function change data is in screen 3 but we need to get it to screen 4. same process again final function that can accept a string called change data now we could have called it something different for every class but let's keep it the same so i'll have required there and it will be this dot change data okay so now by passing it to screen 4 change data and also using change data there we now have access to the function right here inside of the stateful widget and we probably can change it back to stateful with stateless widget again so now we've got this function inside of screen4 and it's called change data so what we can do then inside of this onprest will be just going to change data now in order to access that you'll need to go to widget dot change data and we can just pass in to that function that string value so let's say we want to change it now to chuck norris another nice guy whose bullets never run out okay so it's widget dot change data i'm using that function now and i'm passing in chuck norris so what will happen it will go up up up up again call this function set that data to data changed and because we're calling set state it will rebuild the ui okay so let's see if that actually works so let's run this again now you can see it's john rambo as soon as i click change data there you can see chuck norris chuck norris so that actually worked now but again can you see what's happening now let me just see if i can change this one back to a state list widget but it's not necessary we can leave it as it is okay so if i click there now that chuck norris has been sent up the tree again right to the top and called by calling set state what actually happens now because we're calling set state inside of this main page state that set state will actually rebuild from here and we can see this you can see that i've got print statements there there's a print statement building main page there's building screen two there's a print statement building screen three there's a print statement building screen four okay so let's look at that i'm going to rerun this quickly so i'm going to rerun this now look at what happens right from the start it builds the main page screen 2 screen 3 and screen 4 okay and that's understandable now look at what happens if i click this button as soon as i click the button it rebuilds every single one of those pages again and the scary thing here is screen 2 and screen 3 should not be rebuilt at all because they know nothing about that data variable that we sent through and that we update right at the top it knows nothing of it i mean screen 2 does nothing with it except for just sending it through to the next one screen 3 knows nothing about it it just sends through now these are very small examples but imagine now screen 2 is a very big layout of its own page of 100 200 lines of coding with a lot of widgets in it and the same for screen three what happens if i send through the data i just want to send through the data to screen four but it needs to go through screen two and screen three in order to get to that one and every time that happens by just clicking a simple button i'm rebuilding in fact my whole user interface and you can see there i'm rebuilding main page screen 2 screen 3 and screen 4 by just clicking that one button so yes you can see that this is totally doable by using only set state and as we've seen on that web page set state is one of the state management solutions so yes it can work but you can see we've got a lot of boilerplate coat going through and you can see if you start building a really big application this will really get you into trouble okay so this is one way of doing it and you can see that we went up until 112 lines of coding by sending through data and lines of coding doesn't matter so don't get me wrong there but we are adding a lot of boilerplate code and the main thing here is screen 2 and screen 3 knows absolutely nothing or should not know anything about the data that i'm passing through or sending back to update but it does at this stage and also screen 2 and screen 3 because of that gets rebuilt which we do not want and that could affect the performance of your app right so what i'm going to do now i'm going to leave my main. and i'm going to create a new file i'm going to call this one main 2. and i'm going to paste that same coding again there's the same data again you can see it's the same as we had previously and now what i'm going to do is to see if we cannot do this in another way that actually makes a little bit more sense and there's a lot easier to maintain and at the same time make sure that screen 2 and screen 3 will know nothing about that data so we actually want them to stay exactly as they are without adding any coding to them right so now going back to this web page you will see that there is provider and this is the recommended approach and you can just right click there to open up the link in a new tab for the provider package and you can see it opens up pub.dev with provider 5.0.0 and you'll see it's published on march the 4th 2021 and if you look at versions also for this you can see that this thing started way back in october 19 2018. so this provider package has been updated a lot to make better and better and better another way to get to this in the future just go to pub.dev and search the package for provider so that's also an easy way to get to it and this first one uh provider five zero zero it's the newest one currently at the time of this video so if you click on provider you can go to installing and you will use this line there provider five zero provider500 so we're going to copy that and we're going to use it inside of our pubspec.yaml so as part of your packages just underneath your cuppatino icons we're going to paste provider and i'm going to save and that will include this provider package for me now i'm going to stop this from running because currently we are running main two or main. so we want to run main2. now because we've added a new package in the pubspec.yaml whether we were running whichever one doesn't matter it's better to stop it and then rerun again because we included a new package okay now let's go to dot dot so i'm gonna run this one so by just right clicking and saying run without debugging we will now be running main two dot dot right so now you can see it's running and just make sure that at the bottom now you can see i'm launching main2. so if i make changes it's the changes on main2. okay so let's go down and let's see how we can include the provider package now or how we can use the provider actually package to actually help us so what we want to do is to go and identify where in the tree do we have the data that i want to set so in this case the data year is where i want to go and change data as well as there on these two text widgets okay so in order for this provider package to actually help us we can go and create our own model class so for example i'm just going to call this app data because we it's just a simple string value that we're passing through and what you need to include is with change notifier now if you use that change notifier at the top okay it's part of the material package so for that change notifier or for this class app data it says with change notifier so it's a mix-in basically that helps me to notify of any changes that happens inside of any instance of this class and we'll look at that concept now so the provider clause will need some model classes that you were going to work with that uses the mixing called change notifier so change notifier like the name says it will notify of any changes inside of the instance of this class okay so inside of this class i will now declare the data that i want to change so instead of me having to go and declare final maybe here final string equals john rambo right there at the top i will do it right here so i'm going to say string and i can even name it with an underscore which means i can make it privately so i'm going to say string name equals and let's have john rambo there and then all i need to do if i want to change it i want to go and call a method or a function so i'm going to call this one void change data and i want to accept some data and that data will then be set to this name so i will basically go and say go to name and set it to this new data that was passed in but now an important thing that's a bit different here is we need to call notify listeners so you'll see now what we will do inside of our widget tree we will mark the values that needs to change so for example i will mark this one as something that needs to listen for updates on that class i will also go and mark this one to listen to updates from that class called updater or appdata so as soon as data inside of this class is changing for example if name gets a new data then we notify all the listeners and those listeners know that it needs to update the value and to rebuild the user interface okay now also another way or another thing that we should add here is to get back this name so if obviously if you do not name it privately you can just call it by saying going to the object dot the name and you get the name when you can set the name is the same by just using an equal sign but if you want to have it private like i have it now i will need to create a getter for it so the getter let's call it the same but just not with the underscore and that will return back this name for me okay so the getter method or the getter function there will return back the name called john rambo at this stage okay and that's all we need for this model class and now normally you would put this class maybe under a folder called models and add this class in its own file called appdata.dot or something like that i'm just going to keep it inside of this file so that we see it and it's easy to work with right so now the idea is that i need to go somewhere in my widget tree and use a change notifier so what i'm going to do here is i'm going to go into my scaffold i'm going to use the control dot and i'm going to wrap it with a widget called change notifier provider now if you hover over this change notify provider you can see it's got or it wants to have this create there's a parameter called create so we'll set that now so you can see there's create there's a child and there's a builder so i'll show you now it's going to give us an error by just using child but in some cases in most cases you can actually just use the child as it is now but in our case because it is really too close to the parent which is the scaffold it's going to give us an error okay so for this change notifier we'll need to use the created and for the create leave your cursor there and use the fat arrow because this will just be returning an instance now of the class that we want to use so this is the model class we want to use that's got the change node to fire mixin and it's called app data so what i want to do then here is to go and just call this app data and basically just creating a new instance of that class so it's an object now called appdata and that is the one it needs to listen for updates so this change notifier provider will allow widgets now underneath it to get marked to listen for changes inside of app data so if we save this now you will see that nothing really happens because we haven't marked this one to change so let's see how we can mark this text widget now to show the data that is contained in that appdata clause so it's the data here this name john rambo we want to show now inside of this text widget so all i need to do is to go into this part and use the provider class dot of and just before the of and the bracket you'll need to display the type or to show the type there so this will be of type app data so it's the same class that we created at the bottom it's the same type i want to listen for changes inside of that class and then after the context if you put the dot you can see we've got access now and yes we've got access to the underscore name because even though it's private there remember it's private inside of this file so if you have this in your own class you won't be able to use that dot and use the underscore name okay so do not use that one so name is that getter that we created so this getter there at the bottom just calling name will return back that name for me okay so now we've got we basically marked this text widget to listen for changes on that name variable so it gets marked and as soon as something changes in that name variable it will update this text widget now if we run this now let's run that quickly and see what we get okay we get a nice error and this is the nice thing about this remy guy just look at the details of this error and it tells you basically this happens because you use the build context it does not include the provider of your choice there are a few common scenarios you added a provider in your main.dart and perform the hot reload uh the provider you're trying to read is in a different route or you use the built context that is an ancestor of the provider you're trying to read so this is basically what we did now is we had this one too close marked this one too close to actually the scaffold which is the child now of the child notify provider so in order to overcome this and this is the recommended approach also i will i will recommend doing this is to not use the child like we did now here so the scaffold is the child but instead of using the child i'm going to use a boulder they so for the builder just hover there and leave your cursor there and choose this one that says context child with the brackets okay and all we need to do then is instead of using this child property here so i'm going to copy that whole part there i will return it in here so i'm going to say return scaffold and just end it off with a semicolon okay and then this part for the child we can totally remove now so i'm going to remove that and save again so this is the structure you will have your change notifier provider at the top it must have create and then also use builder so this is the recommended part otherwise you could run into that same type of error that i just had so rather use boulder than using child so instead of using child we use boulder and we return that child so the value for the child we will just be returning so we will be returning a scaffold with an app bar and this one there will be listening for changes and you can see john rambo is now there so i have that data there by saying provider of app data go and listen to app data and if app data's name changes i want to have it updated here so in this case it didn't change but right from the start when we ran it we've got that value now directly from that clause and that's the default value so john rambo is what we had there john rambo so that's what it's displaying right from the start now another thing that's very important here the second argument is part of this context there's also a listen now this listen is it has got a default value of true which means that if you have a widget in your widget tree that needs to listen you can just leave it as it is you don't need to change the listen to true because that's the default so just leaving it like this is the default listen is true so which means it needs to listen does it need to listen yes or no yes it needs to listen for any changes inside of app data in in specific that name variable so if you go down you can see it's a change node to fire it's the mixing call change notifier so as soon as this data gets changed it will notify the listeners and this one will listen for it so that's why we need to have this listen as said to true but that is also the default value there so you don't need to set it if you know you're going to listen for true or you're going to listen so you don't need to set it to true you can just leave it leave it as a default there okay so now you can see john rambo is showing there at the top so how will we then show it also there at the bottom well it's exactly the same way so i'm going to copy that one again and let's go to the bottom where we've got data here and i'm going to do exactly the same thing i'm just going to say provider of app data again context and name and save and there we see john rambo can you see that i did not pass through any values from main page to screen to to screen 3 to screen 4. i'm just using provider with the data it needs to listen to and then it will show it for me okay again listen is set to true here let's look at something else because now we are just basically listening for changes and we're getting that value back and we have it on the widget but now how can we use this change data so the place where we change data is in screen number four and now let me just quickly handle this also you can see that i've got this text widget here but i don't have a changed notifier provider in here which means that this change notifier provider works for everything in the same widget tree going down so everywhere underneath this we can mark it for that same data type app data and it will listen for it okay so what the creator of the package then also recommend is that you go as high up as needed don't go higher up than than what's needed for example i could have placed it above this material app but it won't make sense because i'm only using it in this scaffold so then i'll place it right above the scaffold and start using it from there so don't over scope it and now everywhere from here on down the tree i will have access to this app data and i can look at the changes that's what that was made right so going down that's why we can use it here because screen 4 how do we get to screen four we go to the scaffold then we open up screen two screen two opens up screen three screen three opens up screen four and screen four is where we have it so it's down the tree so it's working fine okay so let's see in this on press now if we click this button we want to actually now change that so now it's easy again i still going to use provider again dot of again i'm going to indicate the type where i want to change and that's app data and now as part of this i will use the dot again and you will see there's my change data so that change data function there is this change data function i have there so i'm just going to provide a same as we did here provided out of app data again the type context again instead of referring to the variable i'm referring to a functional and it's called change data and all i need to do is change the data here now so if i change the data now let's say to let's go with chuck norris and i save it now what will happen now as soon as i call change data and i pass through chuck norris what will happen chuck norris will now be set to this name variable and we will call notify listeners so where is it going to notify everywhere we've got that listen property so i'll have it there and i'll have it there so those two will then update so let's see if we run this now what we will get i'm going to run this again now let's look at what happens when i click this button click the button ah we've got a nice little error again and the error that we've got here let's quickly explain this error for widgets the value that we need to have here is listen true and that's the default so you don't need to set it like i'm doing it now and the same year if i go there next to that context i'm actually using listen true okay so if i go down this part here is not part of the tree so the elevated buttons function is not part of the widget tree and if you are calling the provider of with app data in the context and you are not part of the widget tree then you must go and remember to set listen to false so if listen is not false it will also actually try and listen but there's no widget it needs to update okay so make sure you set it to false then and if we run this again you'll see john rambo there if i click on change data i can see chuck norris at the top okay so you can see everything working as is as expected now so very important when should you use true and when should you use false if you have a widget where you need to listen for the data then listen must be true if you're going to use it in a function where you want to only get back the value and not actually set the state then you're going to set listen to false so for example instead of saying dot change data there i could have just gotten that value name but i'm not need to i don't need to listen to it so let's say we just wanted to print out this value so i can print out that value of name where we've got now save it so let's go to the bottom if i click this now you can just see it prints out the value so whether you're calling a method or just getting back the data for whatever reason you will set listen to false because it doesn't need to update any widget now so just make sure of that so in our case we will not print out anything but we actually want to change the data so i want to call that function so i'm going to call the function called change data and we're going to set the data to chuck norris okay so let's save that again let's change it to something else uh peter norris or morris okay that's fine okay so if we change it now if i click on change data you can see peter morris changed everywhere now look at this again very interesting right at the top we've got this change notifier provider that creates an instance of this class and we've got the builder that returns back basically the rest of the widget tree i've marked this text widget as something that needs to change by using provider of specifying the data or the data type there and it needs to listen and we're going to listen for that name variable if it changes it will change this okay why does it change because we've got this method called change data that will notify the listeners so this line here is basically just adding a listener for this text widget and will apply that value as soon as it changes now if we go down again the same thing happened here we're marking this text widget to listen so you can see listen is true although that's the default so you don't need to have it okay so it's listening and as soon as that value gets changed and it's called notify listeners it will also update the value here now as of the release i'm not sure when it's some of the newest releases now of the provider package there's actually a new way to do this i'm just going to show you this quickly instead of having this whole thing we can actually just go and say context dot and there's two functions that you can use you can either use watch or you can use read so let's use watch here so i'm gonna say context sorry context dot watch the type i need to watch for is again app data and i want to watch which value name okay so you can see it's a lot shorter than using provider.of and so forth so this one does exactly the same thing so it's it's just a shorter way of doing this and it's the recommended way so you can just say context dot watch app data and then go and refer to whatever you want to use now this watch one let me just copy this one i'm gonna copy it and i'm gonna use it at the bottom so at the bottom there instead of using this whole thing we will be using only watch and if we run this again let's change this to john let's add my name there and i'm gonna save it again so when i click on it it's still changing everything still works the same so it's a shorthand way of doing exactly the same thing so very important this watch function sets that listen to true so you cannot use watch here so in in this case if you wanted to do or replace this with a shorthand you're going to use context dot read so the read function will set that listen property to false okay so if i save that so that's the difference between the two you are either going to use watch or you're going to use read watch inside of a tree inside of a widget and read wherever you're outside of the widget tree and it doesn't need to listen for changes then you're going to use read so it's just reading the data and calling the method or the function there or reading and just calling that value okay and that's the the shorthand route to do exactly the same thing so i don't want to rerun this every time so let's make this chuck norris again and save it so if i click now i should see the change there okay so we've got an error it's because we need to specify the type here okay so it's going to be app data let's save it again okay let's just rerun this one quickly okay we're back at john rambo clicking it back to chuck norris okay so now everything is working as expected and again the only thing we did was to create a model class called appdata that uses the mixin called change notifier if there's a change it will notify all the listeners that's listening to this app data and we do that by supplying a change notifier at the top in the create we basically point it to that class that we want to listen and we have the builder that returns the rest of the widget tree wherever we want to mark something to listen so this is how i market to listen for a specific value so this one listens for name and then also the one at the bottom this one listens for name as well and as soon as we call this function by just going to context.read app data change data as soon as i pass through that value it will set the new value and it will notify the listeners all those that listened which is this one will refresh the ui and if we go up that one will also refresh the ui right all well now let's look at this print statement so you can see we've got a print statement there building the main page building the screen 2 building screen 3 building screen for so let's rerun this again okay so i've run this afresh now so let's look at the bottom you can see it prints out the main page was built screen to screen 3 and screen 4 was built now let's see what happens when i actually refresh which ones do i want to refresh i'm refreshing a widget in screen4 and i'm refreshing a widget in the main page so let's see what happens if i click this button now okay i clicked it now more than once but you can see main page screen 2 screen 4 that was initially when it runs and that you can do nothing about you need that so when i click the button it actually built screen 2 3 and 4 again when i click the button again it rebuilds screen two three and four again and you can see every time i click it it's actually rebuilding the whole widget tree from two three and four okay so what happens is still not very good so the only thing that we have managed to not have rebuild the whole time from our previous one where we just used set state is in fact just a main page that not that's not rebuilding but screen two three and four is still rebuilding again two three and four every time i click that button screen two three and four is rebuilding and that we do not want so even though now we have separated the business logic in a separate class because now it is let me go back to main2 the business logic is now basically in this app data class so the logic of that name being passed through and so forth is somewhere else we separate the business logic but it's still not rebuilding as we want so for example screen 2 and screen 3 knows nothing about chuck norris there that needs to change and you can see it's got nothing in it so yes we've won because we are now using the single responsibility principle correctly so now let's see how we can repair this part so that we actually just rebuild what we need okay so in order to do this we're going to do the following so inside of my text widget this text widget i want to replace now with something else so what i'm going to do basically now for the next part of the video is we're going to mark this text widget to be the only thing that we need to update which means this whole build method should not run we should only update and rebuild this text widget and the same at the bottom we don't want this whole build method or function to run we want to only rebuild this text widget so let's see how we can do that so if you want to do that which i recommend you do is just going and control dot on the text widget wrap it with a widget and you're going to wrap it with a consumer so i'm basically now marking this text widget as something that needs to rebuild and only that needs to be rebuilt okay so if you hover over this consumer you can see it's got a builder widget and a child so again like we did with this notifier this change notifier we will rather be using the builder there okay so let's keep the child there so we we can refer to it back now to copy it from there but we will use the builder so i'm going to use the builder there keep your cursor there and then we're going to use this one context value child now very important you need to set the type of this consumer so the type is again that app data of alice now instead of having this whole text widget there i'm going to cut it from there and remove the child property totally and inside the builder i will just return that text widget okay now because we have if you have a look at this value now that's inside of the builder that value is in fact the app data now so now we don't need this part anymore because we've got that value in value okay so we've got value.name and now that's all we need to do okay so let's do the same thing now for the bottom text so i'm going to actually take this whole consumer there because it's going to look the same okay so let's go down and where we have this text widget i will also replace it with that same consumer so it's a consumer class using a specific data type which is app data it will have a builder to build your user interface for that specific part and it will be returning a text widget which will have the value which is app data and the name so this consumer class helps us to only identify one single part of your user interface that needs to listen and leads to rebuild okay so let's save this now and rerun and see how this changes okay so it's that same print functions again and you can see it prints out main page screen to screen three screen four so now when we click on it when we click on it it should change to chuck norris now so let's see if that changes chart notice and i can keep on clicking that button and you can see nothing gets rebuilt and this is if you want performance this is how you can really boost your performance okay so at this stage chuck norris clicking that button changing the value does not rebuild anything so what it's what does this mean it will basically just rebuild the spot and that's just the text widget it won't run this whole build method and also here it's only rebuilding the spot so it's only the text widget whatever you return okay and that is it for how your provider can help you to manage the state and you can see if you look at this one now maybe it's a bit more complex than the one that we had here because it's sending through this one sent through the functions and the data in order to set the state at the top so maybe this one is a bit easier to understand but main two is way more or maintained or dot this this one is way more efficient and why why am i saying that because by using this model class at the bottom we are separating the business logic and remember app data can now go in its own class so it's totally outside of main2. we're separating the business logic also another thing that's very important is that screen 2 and screen 3 that knows nothing about that data being sent through actually at this stage doesn't have anything and the nice thing now also have a look at this this is a stateless widget stateless stateless stateless stateless i do not have even one stateful widget which means boilerplate code is something of the past okay now very important single responsibility principle the screen 2 has got its own responsibility to do something the screen 3 has got its own responsibility to do thing or something and it has nothing to do with this app data at all now whereas previously in the main. you've seen that screen 2 had nothing to do with data or this function but it needs to have it in order to pass it through the widget tree and the same for screen three it has nothing to do with any to any one of these data that's been passed through but it needs to go through in order to reach screen four and you can see this one yes we could have left the stateless widget that one has left a stateless widget but this one at the bottom we can probably also make a stateless widget but the one at the top where we need to set the state yeah it needs to be a stateful widget otherwise we cannot call set state okay so i hope you've learned something from this video and the next video that we will look at will be going into maybe a bigger example where you will also see how using just set state will really complicate things so i hope that you understand the concept of the provider package and remember you can go and read the documentation for the provider package there's a lot more we also will go into futures a bit later and also how to handle roots with the provided package but that is still to come thank you very much for watching this video see in the next one
Info
Channel: Johan Jurrius
Views: 2,337
Rating: undefined out of 5
Keywords: Flutter, State Management, Provider, State, setState()
Id: rSmKUmltTSM
Channel Id: undefined
Length: 56min 24sec (3384 seconds)
Published: Wed Jun 02 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.