#Google Flutter - MVVM in Flutter using Providers.

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello and welcome back to another collateral tutorial in this video we will see how to implement mvbm architecture in a flutter application so without any delay i'm going to jump into our demo application and i'll be explaining what is mbvm and how to implement it with the help of this example so basically what it does is um it we will have some model classes and we will have a viewmodel class and all of our business logic will be in our viewmodel class so that the basic um uh the basic idea of mbbm is separation concerns so that means your the components in your application should be decoupled as much as possible so that it can be easily tested and also your ui will be much cleaner because all your business logic will be moved to the v model classes okay so the v model will be just notifying the ui about the data changes and the ui will not be in here it will not have any idea about how the data is coming into the ui okay so that it can be easily just separate and it can be easily tested compared to other uh patterns like an ac at all so let's jump in so let me show the dependencies that we are going to use the first one is the provider and the second one is the http so make sure to call flutter packages git in the terminal to install dependencies for your project let me show the service that we are going to use so it's from jsonplaceholder.typical.com it's a list of users i'll be providing the link to it in the description so let's see what's the main idea behind mevm so here we will have a viewmodel class and you will have your view classes and you will have your repo classes right but the main business logic will be residing in the view models and the view model will be communicating to the view and also the uh your repo or your local database or your files etc wherever the data comes in so whenever there is data the viewmodel will actually notify the view or your your screen where your ui is and it will reload by itself that's the whole idea so it's really simple so the view model is actually a middleman between your view and your rapport and uh so whenever there is some change in the data in the view model it will be notified to the ui and it will reload itself so that's the basic idea so what happens is uh you can actually change the v model later and you can change the logic or you can do anything in the view model but the view will not be affected at all okay and the view will only be displaying some of the values from that is being notified by the new model okay so it's much cleaner and it's much it's decoupled and it's easily testable so that's the main idea so uh keep it simple as possible and your view will be much cleaner so without much talking we'll start implementing this so it's really simple in flutter there are many different ways of doing this so i'll be showing one of the ways with the help of provider you can do with a block pattern as well now let's create the directory structure for our users list so i created a folder uses list now we need the views viewmodels and the repo so those are the three main folders we need and additionally i'm creating the models class sorry in the models folder and this is our model i'm copying it and go to app.cubetype.io and paste it in there make sure to change the language to dart and give your model name so it will generate the classes for you the model class for you copy it and let's go back to the editor and create a class users list model and paste it in there so you can see all the number variables so let me so here is address which is a nested object so it created the class for address and also the factory methods to json and from json so let me rename this class to let's say users user model okay so list of user model all right now let's go ahead and create our services class so i created the user services dot dot file and create the class user services import the http package as http we will create the method which will return a future object get users we are returning a future object because uh will be returning multiple type of objects so we'll be seeing that in a moment so let's declare a war url uri dot parse so let me copy the url okay and let me create a utils folder and a constant star dot file and copy the url in there so constant string users list is equal to and paste our url in there let's import the constants file now wire response is equal to await http dot get url so that gets is the response if the response status code is 200 then it's a success then we are gonna return users list model from json and pass in the response body okay now let me create and the file ap status so we are gonna have two classes here success and failure that's going to take two member variables code and a response which is a generic object it can be anything so you can use it for any any service calls okay so that's the idea so let me use it here so it's gonna return success and response user list model from these on let me import it again so that's why our method has a future object as return so similarly it's going to return the failure object when the status code is not is equal to 200 and the error response can be any object so here i'm setting it as a string response so you can set it to any object you want okay so that's why it's it's having the object type and also you can have different error messages for error messages and error codes for different types of values i have already made a video on how to handle different types of errors properly in flutter uh so i'll be leaving the link to it in the description make sure to check it out now our service class is almost done on and let's copy these constant values to our constants file so open the constants file and declare constant user invalid response is equal to 100 no internet 101 and invalid format 102 and the final one is unknown error is 103 so this is what um like if you want to check with the help of these constants in the ui you can do that but it's up to you okay all right now let's create our viewmodel for that uh let's go to the pubspec or dml file so i have already shown we have added the provider package with the help of provider we are going to create the model classes so let's create the userviewmodel class and name it users viewmodel and extend the change notifier this is important now let's declare some variables loading just thing like this all the variables that we used to declare in a stateful widget has been moved to this class and whenever we want to update the ui we will access this viewmodel class get the latest data and update it in the ui these variables are now private because we have added a underscore in front of these variables so we need to write the getter methods to get these variables out of this class so get loading and also get user less model to get the user model now we are gonna write some more methods to set the data into these variables so set loading that's an asynchronous method and set the data onto the loading variable and i'm going to call notify listeners this is going to update the ui or notify the ui saying that there is a new value and that will update the ui so similarly we need to have the set user list model so i'm gonna pass in the parameter and update the variable so here i'm gonna i'm not going to call the notify listeners because i'm already calling it in the set loading so we'll see how that works in a short while so i'll declare other variable user error and set the user error as well user error is equal to user error now we are going to write the method to call our service and get the data for the user list model so get users set loading to true that will update the ui we have not returned the ui yet so we will see that in a short while called user services dot get users it's an asynchronous method so add a weight onto it now if you remember what are the responses for this method let's go to that class and see the responses as success and failure so success if the response is success we are going to set the user list model with the response so the response is an object right so response dot response as list of user model so that's what we are returning from this service inside the success right now the response if the response is a failure we're gonna set the user error so user error is equal to user error code is the response.code because we are already setting the code and error response from the service itself okay now we are going to set the user error and call said loading to false so if you remember we are already calling the notify listeners in the set loading so we don't have to call notify listeners every time in between because uh finally when we called set loading to false that's going to update the ui with the new data from all the uh or the data that we have already set okay so that's a performance improvement so um so so whenever you code make sure you're not calling notified listeners too many times and refresh the ui unnecessarily so keep that in mind when you uh when you're doing a lot of updates okay now let's go on to implement the viewmodel into our view and get the data and update the ui so let's see how we can do that now go to the ui which is our home screen and import the provider package and inside the build method called context.watch and pass in the viewmodel which is the user's viewmodel now we are going to get some errors so go to the main.file and here is an important step you need to wrap the metal app which is a root widget with the provider widget so return multiprovider and pass into providers so you can have more than one provider here and set our material as the child of the multi-provider so here in our case we have only one provider class right so pass in the user's view model here so we are all set now now we can use our uses new model in our classes so whichever that comes under the material app the root widget we can use it there so let's create a new method ui and pass in the user's view model and uh i'm gonna see if it is loading so i'll show a an empty container there for now and if there is some error we're gonna show some error widget so return a container for now and empty container for now and let's focus on the main data here for that let's return a expanded widget with a list view inside it and for the item builder let's return a container for now and for the separator builder i'm gonna pass in the divider and item count will be users view model dot user list model dot length refresh the ui so we are not displaying the data yet right for each row we are just returning a container and uh so let me wrap the ui inside a column because expanded widget needs a column widget or a row widget as its parent we have set the user's v model and we are calling the set loading and false so we had notified listeners there right instead loading method so that's gonna trigger the ui and it's going to come here and we need to return this expanded widget which is a list view of the list of users right so i'm just returning a container with a column having a text with name and email so remember we have not called the get users method right so let's create a constructor for this view model and call get users there let's refresh the app and let me put a breakpoint here and in the ui as well okay it's false so that's gonna show the empty container now get users that return success so so item count is 10 now right so we have the data okay i think there is some issue with the ui but we have the data right now so we have already seen it so let's try setting the style for this text i'm setting the color to black so we have the data there it was in void color and for the email as well set the main access alignment to start and cross access alignment to start okay that aligns well let's give it a padding okay that looks good now let's create a folder components so for loading we were just showing an empty container right so let's create a component for loading widget so a stateless widget class name app loading and uh i'm gonna return a center widget here with a container and child is gonna be cupertino activity indicator let's give it a padding of 20. okay so instead of returning an empty container we will return the app loading so when we refresh we should see the activity indicator so that should be very fast here now okay for that let's let's change the brightness to light and also give it a title so let's go to the app bar and title would be text users so here why don't we create a reusable component for the app title itself so you can use it in any screen so let's create that app title and uh it's gonna accept a title text right so text and uh pass it in the constructor by default i'm setting it to empty so child a text and set the style text style and set the let's set the font size to 20 and font weight to bold so we have a simple component there so i'm sitting and changing the row text as well to this component okay so that looks good now let's create a reusable component for the list row for that let's go to the components let's copy this container here and go to the components and create user list row dot dot and class user list row and instead of that return let's paste our container and pass in the user model in the constructor so this dot uses user model and import the app title here also let's wrap the container with a equal widget so that we can add a tab to the row so that we can show the detail for each user so function on tap and pass it in the constructor and call uses listrow and pass in the user's user model with an ontap function so you see that our ui has not changed a bit right okay now let's create a user detail screen and when clicking on each row in the list view we will navigate to the screen and show the user details so it's coupled with the navbar and title let's leave it empty for now and body which is an empty container and let's create a new file navigation urls and let's write a function open user details this is going to navigate the user to the user details screen so it takes in a context navigator.push give it the context and the route route is the user details screen and while clicking on the row we will open the user detail stream so we'll pass in the context but the user digital screen doesn't have any data right now to display right because we are not sending it anything we are not setting it in a constructor or anything it doesn't have a constructor that accepts any user data or anything so in mbbmd don't do it like that you don't send it through a navigator or something like that we can have it in a state so we already have a state right we have a user state we can have a um this the selected user in the state itself right so let's write those i'm gonna copy the user model here import the provider but how do we get the data so let me create a new variable selected user in our users view model and write a getter and sorry that was a wrong syntax write a method to set the selected user so we will have the selected user in our viewmodel state so that's the function so that will set the selected user and now we need to use this so on clicking of each row we'll set the selected user we're calling the userviewmodel.selecteduser and pass in the user model okay now let's go to the user details screen and set up the ui so app title so that's a widget and called userviewmodel dot selecteduser.name that will be our selected user so similarly in the title also i'll set the name so let's click on each row so you can see that the data is there let's give it a padding okay now a main access alignment to start and cross access to start so now you can see that whenever a user is selected his details is displayed in the user details screen so whenever we are clicking a row in the list view we are setting a calling a viewmodel method to set a selected variable which is a selected user then we are getting that selected user inside the user details and displaying the data now let's add another functionality to add a new user to the list so for that i added a new variable adding user to the user's view model and also a get a function let me set the default to a new user model let's open up the home screen and add a button on the top right side of the screen in the app bar an add button so clicking on this button we will add a new user to the list let's go to our navigation utils and i'm gonna write a new function open add user that will open up a new screen you'll be creating a new screen called add user screen so go to the views and add user dot this is screen dot dot which is also a stateless widget so for this demo all our widgets and screens will be stateless so no state is allowed in any of the widgets or screens so that's how we create a mbvm pattern so none of the widgets or screens is going to hold a state of its own okay so that's the whole idea so our add user screen is also a status widget so it doesn't own a state of its own all the state will be managed by the viewmodel so for our add user also the state will be managed by our user viewmodel i think that's clear let's create the ui for the add user screen that will have a text form field let me copy this piece of code that's how we access the v model let me import the provider so now we have access to our users view model that's called users view model dot adding user dot name is equal to value the value is the value will be coming from the text form field in the unchanged function let's copy that and similarly let's do it for the email so we are setting it to the object that is in the viewmodel adding user let's set a padding for our ui and the spacing after the name and we also need a button to trigger the adding to the list right basically a save button so let's add an action with an icon button and a save icon and let me go to the user's view model and add a function add user it's an asynchronous function and inside that i'm gonna add i'm gonna create a new user and i'll be adding adding it to the list so first let's uh validate each input so if the name is null or empty we're gonna return false so similarly if the email is null or empty then also will return false otherwise it's true now let's use this function in the add user method if it is not valid return from there otherwise add the new user the adding user to the user list model and call notify listeners that will update the ui so once a user is added to the list i'll reset the user the adding user to a new user model so that it won't have the previous values when we are trying to add a new user let's go ahead and use the function inside the the icon button the plus button so call away the user model dot add user let me extract this function to a variable so that it will be much cleaner so user adder is equal to avoid add user and if the user is not added then just return don't do anything otherwise if it is added then close that screen so that should refresh the ui now let's try this tap the save button but i think there is some issue so let's find out and fix it let me open up the diva console and it says boolean expression must not be null so our is valid function is returning a boolean but the ad user is not actually returning a boolean so return true here and let's try that okay okay looking good so we didn't return a boolean in the add user so that was the issue so we fixed it so as you see there is no state here and our ui is much cleaner and we can access everything from the viewmodel anywhere so make sure that your your provider the viewmodel is actually wrapping your screens okay so in this case in our case our viewmodel is actually wrapping the whole application so we don't have to worry now let's go to our viewmodel and we had declared a user error but we were not using it we were actually setting it but never used it so let's use it and show some error in the ui so in the ui method that we wrote we are actually checking for the error so let me create a new component let me say app error this is going to display the error in the ui so map error is going to take a string which is the error text and let's create a constructor that's going to accept this error text so by default let me set it to empty and in the build method let's return a container with a text widget set the color to red and a font size to 18 let's add one more thing here a disability widget which wraps around this widget and if there is some error means if it is not null and if it is not empty then only this widget will show otherwise it will be hidden so i am removing the default value as well so let's use this in the home screen set the error text which is user model user view model dot user error which is an object so convert it to string now let's go to our user services and create an error so that we can display this error in the ui so let me manipulate the url to something wrong so you can see that it's an instance of user error and we have a message field which we are setting uh in the user services which i'm showing in the initial part of the video so dot message and let's see let me set this to center so you can see that that's an unknown error which we set in the user's services so let me revert it back and so you can see we have set 200 as a success so let me create a constant success equal to 200 so this is just a cleaning up of the code so success is is the status code then we are setting the proper data back to the ui to the view model and then back to the ui so you can trigger any any of the errors here and see what is the response so let me turn off the internet and see what's error so that's unknown error i think it's going to the final catch block um i think may i may need to add one more type of exception i think that's called uh yeah it's going here so that's why it's showing unknown error so what if you want to check the internet that's error so that would be socket exception and let me set the message to no internet connection and i turned off the internet and if i refresh the ui you can see that it says no internet connection so that's not part of the mbvm model just a proper error checking so i have done a video on how to properly check arrows in flutter you can check it out i'll be providing the link to it in the description and okay so the this is how the whole view model works in flutter you can do this the same thing with block pattern as well so so these this is the whole structure so the whole idea of the model is separation of concerns and make sure your components are recoupled as much as possible and uh and all your business logic should be kept in your viewmodel and nothing should go in your ui or any kind of widgets so hope you enjoy the video if you do please don't forget to like subscribe and share thanks for watching and see you in the next video bye
Info
Channel: Mobile Programmer
Views: 4,735
Rating: undefined out of 5
Keywords: Flutter, Google, Android, iOS, Tutorials, Code, Study code, SQLite, Cross Platform, Dart, MVVM, architecture, Free Flutter Tutorial, MVC, coderzheaven, code and learn, Flutter examples, Flutter Architecture, Mobile Applications, Androidtutorial, iOS. Tutorial, React Native, Dart tutorial, Flutter Examples, MVVM Pattern
Id: W1e7d3cvnRo
Channel Id: undefined
Length: 34min 33sec (2073 seconds)
Published: Sat Oct 09 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.