MVVM in Android- Model View View Model Tutorial with Project

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up youtube this is dennis paneuta for tutorials.eu in this video you are going to learn how to use mvvm model view view model which is an architecture that is highly recommended by google and that you should learn and understand once you want to build bigger applications so once you want to become an advanced android developer you definitely will need to understand mvvm there are other patterns we're going to quickly look at those in terms of what they are called like in the presentation a little later but we're going to focus on mvvm and this is part two of the series so we're using our retrofit example where we loaded data from the rick and morty api and displayed it onto our application as you can see here and we're going to extend that application so we're going to clean it up build the around the mvvm architecture because it really doesn't make sense for super small projects there just using the simple well building code directly in the main view is totally fine but once you want to build something bigger and want to work in a corporation then using mvvm is going to be the key here okay so let's get started and before we do that by the way hit that like button it really helps us out and hit the subscribe button because there will also be a third part where we're going to then revise our code once again in order to use co routines okay so you're going to learn how to use code routines there as well so hit that subscribe button as well as the notification bell if you don't want to miss out so thanks a lot for watching the video let's get started [Music] alright so let's get started with the beginner's guide to mvvm it is very important that we follow a particular architectural pattern when developing our android applications to promote easy collaboration code reusability and ease of refactoring as more feature changes are introduced into our project there are various existing android architectures which include mvc mvp mvi mvvm well we will be discussing mvvm the architecture what is it and how it helps us develop easily maintainable applications and by the way mvvm is an acronym for model view view model which is an architecture recommended by google for developing android applications mvvm encourages separation of concerns and in this case making sure that the business logic is entirely separated from the view so let's look at the three parts of mvvm so mvvm stands for model view view model okay so the order here however is the model feeds the view model and the view model feeds the view so the view this can be either the activity or fragment it observes data from the view model and should not contain any data logic it is only responsible for displaying the data and handling ui interactions and then we have the view model this is the connection between the model and view and it survives configuration changes and should not contain any android frameworks and then finally we have the model this is responsible for handling the data logic and should not know about the views but rather communicate with the view model okay so other than you would usually use an nvc for example or in other architectures here we are really making sure that the model never directly speaks to the view it's always by the view model all right so let's look at this in practice and build a little example where we're going to use mvvm all right so let's start with the project and what you can see here is that we are using the retrofit example from the previous video and if you don't need to know about retrofit and you just want to focus on mvvm that's fine as well let's just get started so there are three parts to mvvm and they're going to look like this in our case so we have the main activity the main view model the repository and the api service so we're going to use model view view model so this is going to be the concept that we're going to use the pattern and our model are going to be these two classes i'm going to say what sslt stands for and so forth in a bit but first of all mvvm encourages separation of concern and in this case making sure that the business logic is entirely separated from the view you can take the business logic to be the logic that controls the main features of the app and view to be the user interface elements that allow the user to interact with the app and this is what the architecture will generally look like so this diagram is created with this project in mind and shows the main classes that will make up the mvvm architecture so the model which comprises of the repository and the api service then we have the view which is just our main activity and then we have the view model which is going to be our main view model so now let's go ahead and write some code therefore let's go back to our project and here we're going to create a new class which will be the repository class therefore i'm just going to go ahead and create a new class i'm going to call this one repository i'm going to call this one [Music] repository so the repository class is usually the single source of truth so the ssot and the project for instance so if you are going to be depending on two data sources let's say an api and also a local database then this class serves as a mediator between the two sources and knows where to get the data from so that the view model is solely responsible for making the data available for the view to observe okay so let's go ahead and create this repository class it will require an api service so let's pass it to it so here you will need to import the api service class and then inside of it we're just going to have one method that will call the fetch character method from the service class so here get characters at the rubber cryo page and it will call the api service fetch characters page so here this one that we had built up in the last video here this fetch characters okay which basically loads the data from the api so in this case we're only fetching the data from the api with no implementations of a local database but it is still important that the view model has no direct access to the data source to maintain separation of concern and focus on providing data to the activity so you're learning something about android app development in this video and maybe you want to learn a lot more about it then you can check out one of my two courses so if you are a beginner android developer then i would highly recommend to check out my android master class course there you will learn to build android apps from scratch and you become a real android developer or maybe you want to become a better android developer because you are one already and you want to become a real pro then i would recommend to check out the jetpack master class because there you will learn how to use jetpack which is a suite of frameworks that will make sure that you are a senior app developer all right so i would really recommend to check out those courses if you want to step up your app development skills very quickly you can find a link in the description below which will send you to the course with a huge discount all right so thanks a lot for checking out those courses this really helps us out and this enables us to create these videos either way i wish you a nice journey to becoming a great app developer and now let's get back to the video so now before we use the view model class you have to add a couple of dependencies to your project in your build.gradle alright so let's go over here and let's add first of all the lifecycle version that i want to use so lifecycle version is going to be 2.4.0 and then i will require those two dependencies here so first of all the lifecycle view model cotton x extension and then the live data with this lifecycle version so once you have that in there let's sync it sync our gradle and once it's synced we can use it as you can see we also added the live data dependency because the data needed by the activity or fragment needs to be observable and live data is an observable data holder that will be responsible for updating the data to the main activity anytime it changes so observable basically means that there is something that is observable and then there can be a bunch of observers or subscribers that are just waiting for the data to change and once it's changed it will inform everyone who is observing it or everyone observing it will see that there is a change and then we'll take that change and well change the ui what appears for example and so forth so now let's go ahead and create our new main view model okay so here what we're going to make sure of is to create a new kotlin class i'm going to call this one main view model so this class will inherit from viewmodel and accordingly of course it will require to import this namespace up there and then i'm going to pass in the repository to it okay so that's going to be quite important here as well let's make sure of that first of all i'm going to pass in the private val repository which will get the repository from our api client so we need to import the api client using our api service okay so now we create a private mutable live data variable of type list of character and call it characters live data so we can modify the values we need but only within this class and this is why we're making it private so let me add that in order to use mutable live data you need to import the mutable live data namespace okay next we create a getter for the mutable live data with just the live data data type this way the variable cannot be modified outside of the viewmodel class because live data is not mutable okay so let's make sure of importing live data here as well now let's create the fetch character method accessing it through the repository this time okay so let me create a new method in this main view model and we assign and let me close that here so we assign the get characters from the repository which we created in the constructor to a variable and then we create a callback from retrofit overriding the response on failure so let's first of all get the characters on the first page and then use the nq method in order to then wait for callbacks which will give us a character response so let's import the character response as well as the callback but here when it comes to callback you have to be well careful because there are a bunch of different callbacks that you can use and we are going to use the one let me check uh retrofit callback okay so here let me add that and then this object will require you to implement its members okay so we have this object and what it can give us is going to be a response so there is this on response method which we need to implement and then there is also another method that we need to implement that will be the unfailure method okay so these two methods they are required whenever you are using your nq method with callbacks okay and here there's a bracket missing in my case because well it starts here and goes all the way there so that's how we enqueue basically we're passing an object of the callback that we are creating here and well it requires the on response as well as the on failure methods so what is it that we want to do if the response says it was successful so here let me implement that well if the response was successful let's get the character live data and post a value to it so here we're going to select the so here if the response was successful we are going to post the live data so we're going to get the response body and take its result so if the response is successful the character live data posts the data from the response and the main activity will be observing this data to display that on the recycler view so that's the idea right because well this is our recycler view here right and it should observe any changes and now let's also implement the on failure here so i'm just going to log the failure okay i'm just going to say failure and send out the message so let's import a log here for this to well take care of the arrow and now let's call the init block here and pass the fetch character method to it this way once this class is initialized the method is executed and the data is fetched from the endpoint and every class has the init block in it is the first to be executed after the primary constructor so here let's just call the fetch character method and what you also might notice is that this post value here is not very happy with the response that we're passing to it well that's something that we're going to fix in a bit right so i'm just going to comment that out because i want to actually have a screen state that will check if we are loading data right now and if we're loading i want to update the screen based on that okay so what is it that we're doing in this class because there's a lot going on already right so in the main view model constructor we initialize the repository and create a variable for accessing it next we create a mutable live data that will be responsible for posting updates to the activity whenever there is a change to the data we made it private so that it cannot be modified from outside the main view model class instead we created a getter for it so it can only be observed and not changed because live data is not mutable so here this is the getter that i'm talking about then we create a fetch character method and process the response we are basically doing the same thing we currently have in the main activity but instead of accessing the api service directly we get it from the repository so now in the callback when there is a response we check if it's successful and post the data from the response through the character live data and then we execute the fetch character method in the init block since the block is executed once the class is initiated so now let's clean up our main activity and observe the data that has been posted by the law to the live data here in this post value that we're going to fix in a bit so let's go over to our main activity here and first of all i'm going to create a lazily initialized main view model here inside of our main activity so private val view model and i'm going to use my main view model for that as the format and i'm going to use by lazy here what that means is that the view model gets initialized only once it is needed all right and then in here i'm going to use the view model provider i'm going to pass this which means the main activity and i'm going to get the main view model class and now we need to make sure that we get rid of this whole code here because well before that we were taking care of this whole callback inside of our oncreate of the main activity so we didn't separate we basically took care of all of that stuff inside of our main activity and the main activity is the view and the view should not take care of that the view should only take care of things that should be displayed to the user so here instead what we can do is we can now go ahead and just use our view model to observe the character life data so here character live data observe with this and then here we're using a lumbar expression so the observed method takes in two parameters the owner which is going to be this and the lambda and the owner here is the activity so we can use this as the for the first parameter and the lambda which is the observer as the second parameter so here we basically move the code initially set up by a recycler view into the lambda and pass it in the characters and the main adapter and here we just set up the main adapter then we get the recyclerview via its id and for that and for that we need to make sure that we use the characters given to us so here characters are passed to us and actually the other way around like so so the characters that are passed to us that's the one we're going to pass to the main adapter and then we just set up the recycler view so that it uses the right layout we're going to use the staggered grid layout as well as the recyclerview adapter and now when it comes to this character's arrow that we're getting it has to do with the character live data that we get from the mu model so let's figure this out because this is quite a good well challenge i'd say because if we look at this character live data we get it from our live data character in the main view model right and here it's using a list of character but this character that it's using is the java lang character even though i wanted to use my own character class so let's make sure that it's not using that java lang character but instead is using our character so here in the main adapter i used this import eu tutorials retrofit and so forth and we're going to need the same thing so now it should use our character let's move over it you see now it uses eu tutorials retrofit example network which is this character class that we created and in the main adapter thing should be good let's check if the main activity now is happy as well and you see now that is happy as well so at this point if we go back to our main view model it should also be happy with the response body that we are passing to it okay because well that's the thing if you are using class names that are exactly the same as what the ones that are already available and the ide just assumes that it should use the predefined ones and not the ones that you created so that's how we fixed it now let's go over to the next step okay so before we go to the next step i want to quickly go over what's happening here so what we're doing in the main activity so we initialize the main view model lazily what that means is that the main view model only gets initialized once then we use the view model provider to initialize the main view model class which is a utility class for initializing the view model next we observe the character live data to get the list of characters and pass it on to the main adapter and then the observe method takes in the owner and the lambda and the owner here is the main activity so we use this and then the lambda which is the observer called characters now we can run our app and see if the characters get displayed with our cleaner and more structured code and also the main activity well has less less code in it now so it really just takes care of the things that the ui should take care of the view and it takes a care of the ui so we see our code still works as intended which is great so now we separated our view so the main activity from the data so it doesn't load the data directly it does it using the view model which loads the data when it's available and gets the data directly from our response so now let's manage the ui state and when working with data we need to inform the user about the state of information been displayed to them whether it is still loading if there is an error or show them the data once it's available so let's implement a class to help manage the state of the data that has been fetched from the api so i'm going to create a new class called screen state which will be a sealed class so let's go ahead create new class and i'm going to call this one screen state which will take care of the state of the screen and i'm going to make it sealed like so so that it cannot be inherited from so we create a generic field class with two nullable parameters so it will be generic if we want to make a class generic well you use less than sign t greater than sign so now it's a generic class and this is the type parameter here which basically makes generic therefore it can be used to represent various types then we are going to pass two parameters so the first parameters should be of the type t and the second one should be of type string so here we get the t and it can be null so it will be null and it will be nullable and then the message itself which will be a nullable string which we set to null by default as well so we can overwrite this data but if we don't it will stay null so now let's create a subclass and call it success so inside of the screen state i'm going to have this subclass and this will be used once the call was order response was successful and now let's create a second subclass which will take care of when the state is loading and then finally let's take care of an error subclass so this one will take care of when we get an error so to summarize it here we create a generic field class with subclasses representing the states a generic class is one that the type can be specified at the point of use so the type parameter t makes it generic and therefore can be used to represent various types now let's modify this for the main view model to actually use the screen state i want it to display when there is well the screen is loading or there was an error or something like that so first of all let's wrap this mutable live data list with our screen state okay so here i'm going to add the screen state like so [Music] screen state and i'm going to pass the list of characters to it like so and now accordingly we need to make a change here as well so the live data will also use the screen state and pass the list of characters to it so now that we have our getter and we have everything set up let's post the loading state before we enqueue the callback for sending the request we post the loading status to indicate the loading state the loading parameter is expecting a data which is going to be a nullable and since we can't get any data at this point we will pass no so that means here when we fetch the character just before we start loading so we set up the client and before we enqueue let's set the state of our character's life data to be the screen state loading so you might recall screen state that was the subclass called loading and now we're passing null to it okay next let's check if the response is correct you see now the post value doesn't fit the structure anymore so we need to make a change here because here we now need to also use the screen state and say if it was successful so if it was successful now let's pass the list of characters and the response here now for this to work i need to make a quick change to my live data so this character live data that i'm using is going to use a nullable here so i need to make that quick change adding the question mark here same needs to go for the private live data here as well so this private var needs a question mark and then you see this error disappears because while we're working with nunavuts and then you just need to work with question marks every now and then so here what is if their response wasn't successful well then i'm just going to send an error the response code so i'm going to basically do the same thing post the value screen state this time it's going to be an error with the response code to string so whatever the response code was the error response code that we're getting should now be passed there and the data well we're going to pass null here and then finally in on failure so if things went wrong as well well here we can actually get the result and let's display it on the screen for the user so let me get rid of this log you can of course leave it in there but now we're going to post the arrow directly as well here with the message to string okay so let's sum it up real quick so in the main view model first we make the live data hold the screen state instead and then pass it in the list as a type to the screen state since the screen state is expecting a nullable we add the null question mark as you've seen to it and then we use the different states by posting the loading state just before the request is enqueued so we do that here this is the loading state then we're loading trying to load it if it was successful we showed the success if it wasn't successful we show the error screen and then on failure we show the error screen as well so now we need to check for these conditions and when observing this live data in the main activity because the main activity now still doesn't know about the screen state stuff or at least it doesn't do anything about it it also isn't happy about this characters anymore so let's make a couple of changes to our main activity because now in the main activity i want to have another method that will take care of the response that we're getting so let me create a new method that will take the screen state and do something based on it so here process character response it takes the state which will be the screen state which contains a list of characters optional so here i'm going to check when the state has a certain condition let's say the state is screen state loading so is screen state and here the loading so while it is loading do this and here we will then later on add a progress bar so to do add progress bar okay and then if the state is not loading let's say it is success so here if it is success then we want to load the adapter so basically do what we have done here so let me cut this piece out here and actually will look a little different so we still will need to get the adapter but let me get rid of this whole surrounding stuff here basically we will check if the state has data meaning it is not null and if that's the case then load it now of course the characters will not be what we're passing to the main adapter anymore because it will be the state's data so now at this point our main adapter won't be very happy so here let's change the main adapter well i still thinks we want to use the characters here this other character let's fix that in a bit let's also take care of the final screen state here so if the screen state is error then well we can display an error and here we get the state data error because well it thinks that this character is in fact the java lang character so let's make sure that it's not going to be a java lang character and i want to import my character here so here character well we had that character let me copy it from there and now this character here should be using my character and now this error will also disappear so again the same problem that we had before so maybe it's easier to just make sure that you have this line from the get go okay so what did we do here well okay so then there is just missing that we are actually observing the live data so let's make sure that we observe the live data here as well view model character live data observe the state of the well and then we're calling our process character response which will take in a state okay so we're going to pass the state and then that will take care of then either saying okay we were successful so let's display it which is great but what do we want to do if it's loading or if there was an error well for that case i'm going to just add a progress bar to my application and that will be inside of my resources here so in the layout activity main so here i'm just going to add a progress bar here and i'm going to make it invisible which means the android visibility should be set to gone so this is just going to be here a little progress bar that will display well we're waiting for something okay and something is loading so that's what we're setting up here so going back to our main activity and the process character response in the loading part let's make sure that we are actually making this thing invisible so this progress bar invisible therefore i'm going to set up my progress bar using find view by id here i'm going to call this thing pb standing for progress bar find it by its id and i call it progress bar so if you check it out it's in fact this thing here so it has the id of progress bar now you could give it a more descriptive id that would be fine as well so when it's loading so when our screen state is loading i'm just going to make sure to make this view visible so this progress bar visibility set to view.visible so you're learning something about android app development in this video and maybe you want to learn a lot more about it then you can check out one of my two courses so if you are a beginner android developer then i would highly recommend to check out my android master class course there you will learn to build android apps from scratch and you become a real android developer or maybe you want to become a better android developer because you are one already and you want to become a real pro then i would recommend to check out the jetpack master class because there you will learn how to use jetpack which is a suite of frameworks that will make sure that you are a senior app developer all right so i would really recommend to check out those courses if you want to step up your app development skills very quickly you can find a link in the description below which will send you to the course with a huge discount alright so thanks a lot for checking out those courses this really helps us out and this enables us to create these videos either way i wish you a nice journey to becoming a great app developer and now let's get back to the video accordingly of course once the screen state says it was successful i need to make sure that i'm making this view invisible again so i'm setting the view gone for my progress bar here accordingly of course in my error state i'm going to also make sure that this view is gone because well before it was loading right and then i'm going to get the root view from my pb which means the parent and inside of it i'm going to display a snack bar so here let me import snack bar which will basically then display the arrow so it takes in the view in which it should be displayed so i could say this but i will make sure that i'm using the right view which is our activity main xml so here with this line here with this root your line here i'm basically saying hey tell me in which view you currently are which is inside of this main activity xml file and then we're passing this view and we're passing the state message so whatever the error was or whatever if you look at the state here in the arrow case we also get the message here and that's the one that we are now passing on to our snack bar to display the arrow so that is pretty much it you can see that our main activity is really taking care of only view things our view model is taking care of connecting the view to the model but not directly but indirectly so you see we don't have an error here it loaded perfectly let me turn off wi-fi let me actually go into the airplane mode and refresh the application or reload the application let me terminate it entirely well there was a loading screen really quickly as it seems it ignores my airplane mode let me turn android wi-fi off well doesn't seem to want to do it either way let me re-run it we see the loading screen was displayed and then it just worked now if you want to fake an error you could deactivate your internet connection and then you could try it or you can deactivate the internet connection your settings here and then you can try it once again because here in cellular you can turn off well change the speed to gsm try it again so terminate here with the gs7 will be significantly slower potentially even throwing an error because now the internet speed is set to well as if we were 200 years in the past it feels to gsm so if i go back to full now well it seems like it's still loading slowly all right that is pretty much how we separate it and set up an mvvm of setup so we have our model which is the repository and the api service so the repository class that we have set up here this one is our single source of truth so it gets the characters and it uses this remote api service and then it feeds the view model which then has the observer which is our main activity the view which just waits for the live data to appear and once it's there it uses the live data here once it's there it calls this process character response basically once the data changes so whenever the character live data changes it's going to call this process character response and then accordingly it will run all of this code alright so you made it all the way to the end now you know how to use mvvm so the model view view model concept and you can basically use this architecture for your own applications so i hope you enjoyed this video if you did then please hit that like button and if you haven't subscribed yet now is a good time to do so and also don't miss out on the next video that i'm going to upload next week which will be using co routines so we're going to extend this application that we have built here in order to use co routines and this will make our application even stabler and also make sure that we are using the best practices that google is offering and also well expecting us to use so see you in that video hopefully and have a nice day
Info
Channel: tutorialsEU - Android
Views: 821
Rating: undefined out of 5
Keywords: mvvm, mvvm tutorial, mvc vs mvvm, model view viewmodel, mvvm viewmodel tutorial, mvc, ViewModel, MainViewModel, android mvvm, android mvvm architecture, android mvvm tutorial, android mvvm kotlin, android tutorial, android architecture components tutorial, android architecture components, android room tutorial, android viewmodel tutorial, programming, android development, androidviewmodel example, kotlin, components, android kotlin tutorial, denis panjuta, denis panjuta udemy
Id: eUQebUJLnXI
Channel Id: undefined
Length: 40min 42sec (2442 seconds)
Published: Tue Oct 05 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.