Model View View-Model (MVVM): Getting Started

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video I'm going to show you how to get started with the architectural design pattern known as mvvm or model view viewmodel mvvm is actually my personal favorite way to structure code it's my favorite for a couple of reasons number one is that the UI components are kept away from the business logic so all of the views and the widgets that are on the screen have no idea how the data gets there or where it comes from they just display it and number two is the business logic is kept away from the database operations so the business logic part of the code has no idea where the data comes from or how it gets there it just deals with it and then passes it to the views and number three it's very easy to understand and read and that's because everything has a very specific place to live like I said there's a place for the views in the widgets there's a place for the business logic and there's a place for all the data to come from or to be queried from and my fourth reason if mvvm is done correctly you'll have a lot less to worry about when it comes to managing lifecycle events for example screen rotations or if the user closes the app and then comes back to it several hours later if you use mvvm the lifecycle state of the app will be maintained and the app will be in the same position the same exact state as when the user left it okay so you probably a couple questions number one is why don't I regularly use this in my videos and courses because you probably don't see me use mvvm at all I don't think I've used it in anything the main reason for that is a lot of people a lot of beginners especially don't know about mvvm or they don't really know how to use MVM correctly yet so that's why I don't use it regularly but I plan on making it more of a regular thing from now on because it is my favorite way and I think honestly it's the best in most situations - the best structural pattern to use so here on the screen is the application that we're going to be building in this video it's a very simple app it's just a recycler view that contains a list of images with some title to those images so this is basically just the recyclerview tutorial from from YouTube that I have but it's done completely with mvvm and the it does one special thing so if I click on the floating action button down the bottom here a progress dialog will show up on the and a new entry gets added to the list two seconds after I click the button so this is to demonstrate the power of mvvm in this example I'm going to use observables live data observables to observe that a change is trying to be made to the recyclerview and then once a change is made the view is done updating the progress bar is removed and that item is added to the list so before we get started with the example I just want to talk a little bit about how this generally works how this system is supposed to work and so right now I'm on coding with Mitch comm I'm at the blog post that I made about mvvm and I'm viewing a diagram that's in the blog post you can see this is a blog post on my blog so this is just if you want more reading you want a little more information check out that blog post so this diagram is outlining an ideal situation when you'd want to use mvvm the situation comes up in a lot of apps a lot of apps use a rep like something like a REST API to grab data from the internet using HTTP or something like that and then they have a local cache of that data stored on the device and that's what's happening in this diagram so on the left you have your room SQLite database which is acting as a database cache and on the right you have a remote data source which is being retrieved by retrofit which is a library an HTTP library and so retrieving it from a web service or in other words something like a REST API this diagram showcases the module or ization it's hard to say that word maude realization of the cache the data source something called a repository the view model and then the activity or the fragment or the view that the data is being displayed in so the idea here is to make kind of compartments that have a one-way street to communicate so I'll start up at the activity or the fragment so that's what's displaying the data that's got like your recycler view or whatever kind of view that's displaying the data could be text views could be anything like that the view model is what holds what's called the business logic so that's all the handling and the dealings with of the data itself it could be you know all of your if statements to decide what's going to be displayed in the recyclerview or the textview kind of things like that just all the logic behind what is going to be displayed in those particular views and I think the Android team did a really good job at naming this class it's called a view model class so you're gonna be building a custom class that extends view model I think they did a really good job at naming it because that's what it is it describes it perfectly it's a model for a view the view is going to be the activity or the fragment or the contents of the activity of the fragment and inside here is is the model so the model of what's going to be put into that view in our example program here in the view we have a recycler view that contains a list of locations so the model is a list of locations that's what we expect to be contained in the view model it's going to contain all the data involved in displaying what you see here on the screen so there's going to be a list of images with their names probably some kind of ArrayList with a custom data model next is the repository now the repository is kind of like a hub for making database queries or managing data managing the data that gets sent to the view model the repository is the only thing that has access to the data sources and there can be there can be any number of data sources that's that's the beautiful thing about this you have one repository and it's being fed with any and all of the data sources in this case we have two data sources the room persistence library which is the database cache or the remote data source which is coming from a REST API or something like that but there could be more this is just an example the key idea to take away from this diagram is the module ization of everything here so you have your views being separate from your business logic or your view model your view model is separate from your repository which is a hub for all the data and then the repository is separate from whatever number of data sources are coming into your application so here I am in Android studio I've created a new project and there's not much in here but I'll just quickly run through everything so that you there's no surprises so the I have a couple packages one is the adapters package the models package repositories and view models right now repositories and view models is empty the adapters contains the recyclerview adapter if you don't know how to build a recycle of your adapter check out my recyclerview video on on youtube it's free I think it does a really good job of explaining how to design a recycler view from scratch so check that out next is our custom data model it's called nice place so I've I opened this up it just contains a string called title and another string called image URL because if you recall back from our our demo app here each of these list items has an image and a title to that image so that's that's what these are here you have the image in the title the recycle of you adapter then takes in a list of those whoops those those custom data models and then displays them in the recycle of you now I'll just quickly go down to the whoops down to the layout files you just have two here one is activity main which has a recycler view in it we have a relative layout with a progress bar so that there's a progress bar in the middle of the screen you can see if I said that's visible the progress bar shows up in the middle of the screen but I'm gonna set it to gone just to start and then the bottom you have a floating action button pretty standard should be nothing too too surprising here so I'm going to close that the last thing is main activity so right now main activity has nothing but the view components so we have the floating action button recycler view recycle view adapter which is technically not a view component but it's something that supplies a view component with information you have the progress bar they're all being attached to their IDs in oncreate and then the init recycler view method is being called and it's passing an empty list of data right now just notice that this is empty so if I ran this app right now there'd be nothing displayed in the list it's just this is kind of like a bare-bones skeleton of main activity it wouldn't really do much right now once again if you want more information on how to set up a recycler view I have a couple I think of three videos on it so check those out on my youtube channel just search recycler view or you could go to my website coney with Mitch comm and I'm pretty sure they're kind of right on the front page here you have recycle view or go to blog and they're in there so if you need more information that's where I go last thing I want to talk about before we start is the dependencies so I'm using I'm targeting and compiling to SDK version 28 minimum is 21 and down here are all the dependencies for our application this circle image view library is used for making circle image views which are displayed in the list the support design library is used for coordinator layouts or in our case it's going to be used for the floating action button we have the recycler view we have the glide library for actually displaying and setting the images to those circle image views and then up here is the important stuff for mvvm or model view viewmodel these are the two dependencies that you're going to need to use live data and mutable live data which we'll talk about later so this is the data types that are used in mvvm to observe changes in data which is then sent to the views or in other words the activities of the fragments so these are the two dependencies that you need and of course all these codes on github so if you ever get confused or stuck you can just go to my github and go to mvvm example one there's a link in the description and all the code is there okay so I'm gonna close the build Gradle file and close our model class close the adapter I'll leave me an activity open because we are going to need to get back in there later now there's a couple of ways you can go about this I personally like to start with building the view model I like to see what like figure out what I want to display in the view so I'm going to go over to the view models package I'm going to right click go to new Java class and I'm going to call this main activity view model you don't have to call this main activity view model this is just what I like to do typically because that way I know what the view model is for in this case is for main activity so it's very obvious what this class is for I see some developers like to name their view models after the object class that they're modeling so in our case we're going to be modeling a nice place class so they might name it like nice places view model but I prefer the activity or the fragment style of naming this so in our application we're modeling a list of nice places a nice list of nice place objects so that's the data type the datatype that we have in mind when we're making this and we're going to use a special datatype though it's going to be called a mutable live datatype but it's going to be of type list nice place so it's a mutable live data object that holds a list of nice places and I'm going to call it M nice places so I'm sure you're wondering what is a mutable live data object and just hold off on your questions for now I'm going to write a couple more lines and then we're going to talk about it I'm just going to write one more method it's going to be public it's going to return a live data object it's going to hold a list of nice place objects just like our mutable live data I'm gonna call it get nice places and then I want to return our M nice places okay so what did I just do here I have a data type of mutable live data but then I have a method that returns live data but it actually does return the mutable live data so that probably looks pretty confusing it turns out that mutable live data is actually a subclass of live data so what I mean by that is I'll just refer back to my blog post here if I scroll down you can see this right here so here is the class declaration for mutable live data you can see that it extends live data I think the best way to think of it is that mutable live data can be changed in other words it's mutable so if you don't know a mutable means it means it can be changed live data on the other hand is immutable or in other words it can't be changed and I'll show you what I mean so I'm just going to create a method here named public void in it and watch what happens when I type M nice places C I can I have two methods post value and set value those are two methods that are used to change the nice places object but if I was to change this to a live data object and then go m nice places oops nice places you can see that there is no set value or post value method anymore there's some other methods available the takeaway here is that it can be changed so live data can't be directly change there's nothing that I can do as the programmer to be like hey live data I want you to be this now that's not how it works live data can actually only be observed so now that probably sounds even more confusing you can observe changes to live data but you can't change live data but that's kind of the the kicker of this whole thing is you can't change it directly but it can change indirectly and we're going to take a look at how that's done a little later so I'm going to change this back to a mutable live data object and I'm going to delete this okay so at this point in main activity we can actually declare a view model object and get it all set up so I'm going to go up to the top here I'm going to create a new main activity view model object I'll call it M main activity view model and then down here and on create I'm going to instantiate that so I'm going main activity view model equals view model providers dot of passed the context and then get and then we want to reference the type of view model which is main activity view model class and that should be good I'm not sure why it's giving me an error oh I forgot to extend the class so we have our view model class I need to extend by view model now if I go back here that error should go away and I'll close this to give some more room here now the next thing we want to do in our activity is we want to observe changes done to our view model or observe changes done to the objects in our view model or in other words our live data objects so to do that we want to do main activity view model get nice places which returns a live data object and then I want to do observe I want to pass the context and then new observer so inside here is what's going to be triggered the on change method that's going to be triggered when a change is made to our live data object or in other words our list of nice place objects which is returned down here notice if I go into the view model and I change this to a mutable live data I go back into the activity it still works so you can still observe changes to a mutable live data object the reason that you don't observe change to a mutable live data object typically you want to observe changes to a live data object so I'll change this back to live data it's because you know that it can't be changed so if the configuration changes in the application like a screen rotation or the user presses the lock screen and walks away for a couple hours and comes back you know that that data is going to be the same the data will not change it's going to represent the exact same thing they saw before the state change of the activity or the fragment now that we have our view model working inside of our activity if a data if the data is changed we want to notify the adapter that the data is changed and that also means we need to pass the data to the adapter in the first place so I'm gonna go main activity view model get nice places and then get value that's going to return the list of nice place objects from the live data object that's returned right here so that's all great we have our activity all set up ready to receive the data and observe the data from the view model but how does the data actually get into the view model and that's where the repository comes in so that's the next class that we're going to create we're gonna create a repository class I'm going to right click on repositories' go to new and I'm gonna call this nice place repository now normally what you'd want to do in the repository is build your methods or your classes or whatever access points you need to make to access your web service or access something like a database cache but in this video I'm just gonna hard code the data in and make it look like as if it was coming from a web service or from a database cache so first I'll create a static instance of static instance of nice place repository I'm going to call it instance we want an ArrayList that's going to hold our data nice place data it's going to call it data set equals new ArrayList then we create a public static nice place repository return method to get the instance so if our instance is null then we want to sorry instance equals new nice place repository and then below we want to return that instance so what I'm doing here is I'm implementing the singleton pattern I'm going to write that at the top here and the reason I'm using the singleton pattern is because that's what you're going to want to do if you're accessing a web service or accessing your database I'm not gonna do it actually in this video but I just want to go through the correct kind of way that you would want to do it you'd want to create an instance so that you wouldn't have a bunch of open connections to your web service or your api's or your caches next I will make another public method this one's going to return a mutable live data object and it's going to take contain a list of nice place objects so get nice places this is the method that you'd want to actually make your database queries or access your cache or whatever I want to make this look as real as possible so I'm going to kind of go through the motions of what you do if you were actually accessing a database but in order to do that we need a method for actually setting the data so I'm gonna create a private void set nice places and this method is meant to mimic what it would be like to retrieve the data from a database so I'm gonna skip the video ahead here because I have a bunch of code that I need to bunch of repetitive code that I need to put in here okay so I'm just adding a bunch of nice place objects to the data set the ArrayList you have the image URLs and the titles and that just kind of repeats all the way down there now inside of the mutable live data are sorry the get nice places method we want to set the nice places which is mimicking what it would be like to retrieve the data from your web service then create a mutable live data object of type list nice place we'll call it data equals new mutable live data and then we want to set that data so set value and we want to set that data set which is the data set that we theoretically should have retrieved from a API or a cache or something like that then we want to just return that data so this right a little comment up here saying pretend to get data from a web service web service or online source so that's generally how it works you have your repository and it's meant to retrieve the data from some online source which is what we're going to call the set nice places method that's what that does it sets the data to a mutable live data object and then it returns that data now this is how we recover it or we retrieve it from the view model so that's what we're going to go into next now inside the init method is where we want to retrieve the data so if nice places does not equal null then we want to return because if that means that we've already retrieved the data and we need to instantiate our repository object so I'm going to go up top here and go private nice place repository I'm gonna call it M repo then inside of an it I'll go em repo equals nice place repository and we want to retrieve that instance then M nice places equals M repo get nice places and that's going to retrieve that mutable live data list of nice places from a repository right here so at this point we actually have some data in our view model the nice places mutable list mutable live data list holds data and we can access that data by calling get nice places so that's what we're going to do in here we're going to go up to here I'm going to call an it whoops ma an activity view model dot and knit and then that's going to retrieve the data from the repository and then we're going to observe the changes and the new data will get updated in the adapter so that's the basic structure I could run this right now and we should see data showing up in our list and there you go you can see that the data is retrieved from a repository it's sent to our view model which holds all the business logic and then the view which is main activity is able to retrieve that data and display it in a list by observing the change in the nice chain or the entice places live data list so that doesn't seem probably all that incredible but it's because this is a really simple example and I want to show you for that reason I want to show you another example just to show you kind of a more powerful thing that this can do so I'm going to create a we're actually going to have our progress bar here so I'm going to go into our main activity view model and I'm going to create another variable it's going to be a mutable live data object because we want to observe changes to it but it's going to be a boolean I'm gonna call it m is updating and it's going to be a new mutable live data object now the point of this boolean is to determine or to I guess represent when a query is getting made to some kind of a database cache or an API so if I was to request information from our repository which is this right here I want a progress bar to show on the screen and then once the data is retrieved I want that progress bar to get hidden so that's what this is going to represent if this is true the progress bar will show if it's false the progress bar will get hidden so I'm going to go down here and create another new method public void add new value it's going to be take a nice place object and it's going to be responsible for adding another value to our mutable live data list of nice places so first things first if we're gonna add something new I want to set the is updating boolean to true because that means that something is changing we're in progress of changing something now to mimic a server request or what it would be like to make a server request I'm going to use an async task and I'm going to sleep the thread for two seconds that way there's a little bit of a time delay so that the progress bar will show on the screen for two seconds and then it's going to go away when it's done so I'm going to write new async task and keep in mind that this is not how you should choose an async task I'm just using it for an example so don't don't do this it's going to give me a warning because you're not supposed to do this so I'm gonna take the doing background method and the on post execute method I'm going to call execute down here inside on post execute I'm going to get a new updated version of the list of light of current places so I'm gonna say current places equals M nice places get value then I'm going to add another place to it so current places dot add now I'll add a nice place that's passed as an input and then I'm gonna go em nice places that post value to submit that new value so current places I'm submitting a new updated version of the list of the live data list and then I'm gonna say M is updating and I want to also post value and said that's false meaning the update is complete now I'm post execute is going to be called after doing background so inside doing background I want to sleep the thread for two seconds it's gonna surround that in a try-catch so I'll try to submit a new value the thread will sleep for two seconds the progress bar will be showing that whole time then when it's done the progress bar will be hidden and the new item will be added to the list the last part of this is building a method for retrieving that is loading boolean so public live data and we want to return our boolean get is loading I wanna return m is our sorry m is ma is updating so it's changes to updating okay now going into main activity I need to first observe the changes to the boolean so main activity view model dot get is updating observe this we need a new observer and I close this just to give us some more room here and then once the change a change is detected to that boolean we need to say if a boolean is true then we want to show the progress bar because that means it's loading it's retrieving more information from our repository otherwise we want to hide the progress bar and we want to scroll to the very bottom position which is the new position now that the new item has been added so we get value size minus 1 the last thing is attaching an onclicklistener to the floating action button and then actually triggering the change so new onclicklistener and then inside here i want to do am main activity view model add new value and we want to do a new nice place and we want to pass some parameters for a new nice place i have these red node ahead of time so i'm just going to skip the video ahead here so that we have the image URL and then a title of washington ok let's run it and take a look and I'll I'll walk you through everything it's happening as it's happening so here we have our list notice if I scroll to the bottom the very last entry is Australia now if I click the floating action button we expect to see a progress bar showing on the screen and then after two seconds a new list item is going to get added so I'm going to click the floating action button and there's the new item getting added to the list and the progress bar is hidden and you can see I can repeat this process over and over because we've hard-coded in that place so it's just going to keep repeating so everything is working as we expect the key kind of takeaway here is that none of the business logic is being done in the activity everything is being done in the view model so I'm pressing a button I'm triggering a change to the view model I'm adding a new value to it when a new value is added to it the boolean is updating is set to true since it's being observed in main activity in here it's being observed right here when it's true the progress bar will show when it's not the progress bar will hide also in the view model once the timer is up another new place is posted to our mutable live data object and since it's being observed that is also updated in the list because we have our adapter and we're notifying that the data set has changed so that's it that's a very basic example of using mvvm in your project and like I said this is my favorite way to design code because everything is perfectly kind of compartmentalized you have your views you have your view models and you have your repositories and everything is kind of separate so if something goes wrong you know exactly where it is and you can very easily test and fix it in the future probably mid-january I think I'm going to do an actual REST API integration with a database cache so if you look at the blog post that I posted just kind of like the diagram here so if you scroll up this is basically what I'm gonna do I'm gonna have a REST API oh we're getting data it's being displayed in a list and it's also we'll see you about the cache I'm not sure if I'm gonna do the cache yet but definitely retrieving from a REST API using mvvm you
Info
Channel: CodingWithMitch
Views: 388,027
Rating: undefined out of 5
Keywords: android architecture components, android mvvm, android mvvm tutorial, android mvvm architecture, android viewmodel, android viewmodel livedata, androidviewmodel example, android viewmodel tutorial, android room, architecture components android, android example, how to use mvvm, why use mvvm, what is mvvm, android livedata, android mutablelivedata, difference between livedata and mutablelivedata, livedata vs mutablelivedata, mutablelivedata and livedata
Id: ijXjCtCXcN4
Channel Id: undefined
Length: 29min 12sec (1752 seconds)
Published: Tue Dec 04 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.