Android MVVM Kotlin Tutorial - LiveData + ViewModel (Android Architecture Components)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
model view viewmodel is an architectural pattern which will empower you to write manageable maintainable and cleaner and also testable code nvvm is also supported and encouraged by Google itself and there are many first-party libraries like life cycle where components live data and view models and many more in the previous video which you can check out by clicking on the car in the corner you will learn the theory behind mvvm and if you haven't watched it yet I recommend you to do so as I will skip explaining some of the big-picture stuff in this particular tutorial today you are going to learn how to put MVVM pattern into practice you will build a simple yet real enough app which will make you understand mvvm on a deeper level it will be an app displaying quotes which you put in and this quote app will have a view model repository fakey database and a simple dependency injection this will give you strong foundation to build on hello welcome to resew code and let's take a quick overview of the app that you will built in this tutorial so hear this right inside this emulator and we can add a quote over here saying hello and this was set barri who else then Mark Twain and when we hit the add code button it's going to be added right over here so now let's get right into creating a new project with Android studio so go to file new and project and select empty activity as your starting point the language of your app should be Catalan and we don't need to include navigation controller for now because we will have only one single activity once everything is built and setup we will rename this main activity to say quotes activity and we are also going to rename the rest so the layout to be also activity quotes just so that it has some kind of a meaning now let's go over to grade those scripts and build a cradle for possible app and all the way down we are going to add a new implementation which will be this line and by the way you can get this from the link in the video description which is gonna take you to reso coder comm over there you will also find a written form of this tutorial so if you want to go through it at your own pace you can do so from that link and let's also change the version of this Android except combat so alt enter as you can also see up top what I am clicking on and will change it to release candidate oh one instead of beta when you're watching this there can be a full version not even a release candidate so change it to the most up-to-date version and now press sing now in the corner now let's go over to activity quotes XML and I'm going to say right off the bat that this tutorial is not focused on making the nicest-looking application so I am now really focusing on making the layout so you can just copy and paste it from the link in the video description where is also all the code in the written form of this tutorial so go ahead and check it out but just so you know what's inside of this layout we have a textview with ID textview quotes which is displaying all of the quotes like i like pineapples by thomas jefferson then also a latex quote edit text author and then the single button add quote that's it that's all there is to this layout and before we get started writing code is important to organize things into packages in a way that makes sense this is how the project structure will look like in this project so we'll hit new and package we want to create a package data this is where all of the database stuff will be and also the models so the quote model then also new package this one's name will be UI and inside UI we are going to put quotes so new package inside UI quotes Android studio will group this thing together by default now take this codes activity and drag it over to you why and we aren't gonna put it into package UI but rather UI dock quotes right because that's the logical place for quotes activity and also for all of the stuff that is related to UI so for example view models right or all of the stuff that's related to quotes UI will go into package UI quotes and we hit refactor here and now codes activity is a part of the quotes package and now one last package so also new package and this one's name will be utilities we're gonna be using a simple form of dependency injection in this tutorial so that's where our injector utils will go don't worry about it now I will explain everything later alright now we can close out this activity quotes and also the codes activity Kathlyn file and actually we can close everything up and we are going to make the quote data class this whole app is centered around quotes so it's probably a good idea to create a class representing a single quote so right-click on data we want to create a new custom file or a class is going to be a class and its name will be simply quote and this will be a data class because its only purpose is to store data and in its primary constructor we are going to have two properties immutable properties public so Valco text which will be of type string and also vow or author author and it's also be of type string all right and then it's also going to have one member function which will be overridden to string function so over I found two string and is going to return string which will be interpolated so dollar sign and the first thing that's inside this string is the quote X and then - and also quote author or just simply author as it's called this property here what do you have a quote object in memory you would usually want to store it in a database to make it persistent when the app is closed and you could use any kind of database from cloud firestore over to local sequel ID or you could even set up your own back and then communicate it with an API using sequel light as a local cache if you want to use sequel light in your relapse you should really check out the an awesome library called the room which makes it's so much easier to work with sequel light on Android and in the world of room databases which is basically a layer on top of sequel light anytime you want to do something in a database you do it through a data access object also called a Dao Dao under normal circumstances a data access object is an interface defining all allowed actions which can happen for a table in the database like reads rise different queries to group things together and all of that stuff that is defined in the Dao however this tutorial is focused on the core concepts of model view viewmodel architecture and adding a real database of any kind would be only unnecessarily adding complexity to this tutorial this is why you will use a fake database and a fake data access object which will save data to a mutable list which is now going to be persistent but for demonstration purposes this is completely fine but you are now going to skip any important steps which are present in production apps and the code will be simpler at the same time so it's a win-win situation so under data package we are gonna create a new class in addition to the quote class which is already present there and it's gonna be a class its name will be fake quote Dow and over here the first thing that we will have here is a FEA database table which will be private vowel quote list and it's not gonna have a type because it's gonna be inferred but it will be of type mutable list and it's gonna be equal to a mutable list off the type is quote and it's gonna be an empty list by default then also we are gonna have a mutable live data and mutable live data is from the architecture components library and live data can be observed for changes which you already know if you have watched my tutorial explaining the big picture of mvvm so we are gonna put here private wall quotes and this is gonna be equal to mutable live data mutable because we want to be able to change the value of this live data from this fake without class and the type of that the mutable like that Holtz is gonna be of type list and quote all right now let's hit import a mutable like that and we are also going to instantiate it over here so once we have a repository we will observe these quotes from their repository and also in the view model we will observe these clothes through the repository as a mediator now in the initializer block so in it we are going to set the value of our quotes live data so quotes that value will be equal to quote a list this is so that we can immediately connect the now-empty quotes list to the mutable I data which can be observed from our classes this data access object will have two functions one for adding another one for getting quotes so fun add quote it's going to accept one quote of type quotes and over here we simply want to add the quote two quotes list so Paul is that add and we want to add that and then also we are gonna update the quotes value which is the mutable clothes value which is the mutable live data so value will be equal to the newly refreshed quotes list and when the value is updated it will trigger the observers for this quotes mutable live data in all of the classes which are observing it and then fun get quotes and it will simply return all of the quotes so which is the mutable live data which is set to reflect the contents of the quote list and we are going to cast this mutable live data to be simply live data because we don't want to be able to change the value of the live data outside of the fake quote Dao class outside we just wanna be able to observe it and also this like that I will hold the list of quotes all right now in a production app you will surely have more than one data access object for example in a chat app you may keep track of the users and also of the user groups and there you have already two data access objects one for users and one for groups and to put all of the data access objects in one place you should really create a database class and actually if you are using the room library having in database is required because it doesn't make sense to have two instances of database class at the same time a database class will be a singleton Kotlin has a nice syntax for Singleton's where instead of class keywords you put an object keyword and while this would be sufficient in our case it usually isn't for production apps because when in use the object keyword you don't have a chance to have a constructor and to pass something in the classes constructor so in the case of room you need to pass an application context to your database and to circumvent this problem you have to create Singleton's in the java way even in catalan so we are going to and angley's singleton which will now be an object but instead the Java way so new class not object its name will be failed at abase and let's first create a singleton part so we are first going to say that the primary constructor is private so that it cannot be invoked outside of this class and the way that we are going to get the instances of fake database is through a companion object so we need to have an instance property which is gonna be referring to the single instance that its present currently it needs to be marked as volatile and volatile means that writes to this property are immediately visible to other threats and it's going to be private for instance of type fake database instance or fake database simply it's going to be knowable and it's going to be equal to null by default and then we are gonna have one function get instance and this will return so if the instance is already not know so if there is an instance already present we are going to return this instance because this is an old coalescing operator if this is not null it's going to return the instance if the instance is no it's gonna return whatever is after this newell coalescing operator so in that case we wanna call synchronised and the LOC object for synchronization will be this companion object so this basically means that two threats cannot be executing at the same time and here we again wanna check if instance is not instantiated already so instance and also null coalescing operator just to be sure and if it's it's still now we are going to return a fake database new instance so instantiate it and also this fake database instance we want to set the instance property which is right over here this instance property we want to set it to be equal to the database instance if you want to learn more about functions like also run and apply in Catalan you can do so by watching this tutorial by clicking on the cart in the corner alright so this can be somewhat confusing for you but just know that this is how you create Singleton's if you would need to have something passed inside the constructor we don't need to do so in this case we will actually need to do so when once we are creating the repository but in this case it's really not necessary for the database but if you are using room you would need to do this either way you are probably not going to have a database which can be wiped once you stop the app from running right you want to have something persistent so if you are using room you would need to do this regardless if you want to do it or not and database is simply a holder for all of the data access objects so we are going to have a VAR quote ow it's going to be set to fake quote dau instance so we are going to instantiate it over here it's not gonna have only a private set of this property so we can set it only from the fake database class awesome once we have the fake database let's create a repository to be a single point of control repositories our classes which do all of the decision-making regarding Apps data should you fetch a new data from the server or is it enough to use the local data do you need to keep five days of where data locally or only three days making such decisions is the job of a repository I know having a repository class and this particular project may seem a bit redundant you only have a single data access and you don't even have a back-end while this is true this doesn't stop you from learning about the core work their repositories have to do which is being the single source of truth for all the data which view models requests again it doesn't make sense to have multiple repository object so it will be also a singleton this time you need to pass in the fake quote Dao for repository to be able to fulfill its role so you will actually have something in side the constructor for the repository you will use a dependency injection to supply this fake withou instance to the repository so let's first create the repository class and then I will explain the dependency injection and why it is really needed so we are going to create a new class its name will be quote repository it's gonna have a private constructor which will get one private Val quote Dao of type fake O'Doul and it's also gonna be in a singleton so let's copy the singleton instantiation from fake database class paste it inside quotes repository and instead of fake database we're gonna return code repository and also the type of the instance will be quote repository also in order to create an instance of code repository we need to pass M the fake quote Dao so the get instance method will need to have one argument kodou of type fake well Dao and in psycho repository constructor we are gonna pass it over there and now it's all working so code repositories are mediator between database and view models we are going to create two functions one for adding quotes another one for getting quotes just like in the data access object so fun add quote it's going to accept quote of type quote and it's going to simply get quote Dow which is the property defined in the constructor and is going to add a quote on this Dow and the code that's added is the code which is passed inside this function and then also fun get quotes and this is simply going to return quote Dow that get quotes which is the mutable life data actually the life data because we have casted it inside the Dow so get quotes will simply return the live data which is present on this quote Dow right over here and this may seem a bit redundant so imagine a code which checks and updates the back end when there is not enough data in the local database and all of that kind of stuff when you have all of this you know that you have done quite a bit of work already now it's time to connect what you created to the view part of mvvm in this case the view will be the quote activity activities and fragments are therefore merely displaying things on the screen and also handling the user input all of the logic data manipulation with the data goes to a view model then the view only calls functions on the view model this way the data doesn't get reset when an orientation change occurs and so on because it's not present in the lifecycle bound view but rather inside the view model which is not really bound to the lifecycle it's only destroyed once the activity is destroyed for good but when there is only some configuration change like for example when you rotate the device the view model doesn't get destroyed however the activity or fragment does get destroyed so inside the package UI quotes we are going to create a new class content file or a class it's gonna be a class and it's gonna be quotes view model its public primary constructor will get a private Val Quotes repository this class will inherit from view model which is from Android X lifecycle and here we will have two functions one for getting quotes which will also just simply return the get codes from code repository so get quotes and then also add quote quotes of type quote and this will also simply call called repository da add quote and we're gonna add this quote and also import the wrapper package if you are doing something more complex you can also have some intermediate variables and/or fields present in the view model and they are now going to be reset on configuration change however in this simple and there is just no point in having things inside the view model except for these two functions because we have only a single thing that this application does and that is to update quotes on the fake database now let's get back to the code repository for a bit and I need to explain something over here so you can see that we have a quote ow which will be passed to the constructor we are in creating the fake code our instance right inside the repository will create it somewhere else and we aren't instantiate in it right inside the code repository class but you could do that right no because that would break the stability you need to be able to pass a mock version of data access object to the repository for example one that when you call get quotes on that mock object it will return a fake list of quotes which are gonna be always the same for testing this is the core idea behind dependency injection which is to make things completely modular and independent of each other don't create dependencies right inside the class but rather made them to be passed to the constructor of the class all right now all we have to do is to get the dependency injection going and then jump right into quotes activity and make things work right not yet as you can see quotes viewmodel requires a repository instance to be passed to its constructor the way that view models are created or gotten from view model provider this is to prevent recreation say an orientation changes because when you have an orientation change you don't want to create a new instance of view model because they will reset all of the fields that are inside of it and they would negate the purpose of the view model so you need to have some kind of a view model provider which is gonna check oh is there repository or actually view model already present in the memory yes it is we're going to pass it back to the activity so the data inside the view model will not be reset however if it's the first time that the activity or fragment is requesting a view model we are gonna create a new instance and pass it back to there so it's gonna have actually some kind of instance to operate with and because of the view model provider instantiating new view models requires a view model Factory so you simply cannot create view models directly and instead they're going to be created in that Factory so under UI quotes package we're gonna create a new carton file or a class and it's gonna be called quotes view model Factory just like with the view model this will accept one parameter in the constructor we're also gonna save it as a property so private Val quote repository this class will inherit from view model provider that new instance Factory and also instantiated over here it will have one function create so just type create and hit enter it's gonna put this generic function right over here and we are going to simply return codes view model and we are gonna pass in the quad repository which is also present in this Factory and we are going to cast it to be of type T which is from this generic function and we are going to suppress unchecked cast for this function create so as I've already briefly mentioned dependency injection is a way to modularize your code in production you want your view model to operate with a real repository which is fetching data from the servers and all of that however when you are just testing your view model it's a good idea to provide it only with some dummy data so that you can control everything in your tests if you were to instantiate objects directly in each class providing dummy data for testing which is also called mocking would be hard if not impossible you would need to change every single constructor call in every class that you want to test instead you can create all of the dependencies in one place then if you need to test something you know where and what to change there is only one class after all which constructs all of the dependencies so we are going to create a simple but at the same time effective form of dependency injection and you can use a framework like dagger 2 for really complex projects but for now we are just gonna simply create an object injector utils under utilities package so new object injector utils and this is finally a singleton which doesn't require anything to be passed to its constructor so it can be an object and number crazy Java stuff before creating Singleton's this object will have a single function provide quotes view model Factory so this will be called from the quotes activity to get the quotes view model Factory which will in turn instantiate our quotes view model so it will return quotes view model Factory and for now let's write return quotes view model factory and this quotes view model Factory as you can see here requires the quote repository to be passed to its constructor we are going to create a quotes repository so called repository that get instance because it is a singleton and quad repository requires the quote dao to be passed to there so we are also going to get fake data based on get instance and from there we want to also get quote dao because that's where it's present so as you can see here all of the dependencies for close view model factory are created right inside this line of code so if you want to change something if you want to change the implementation you can do all of that from this single function provide called view model factory and now all there is left is to pass the code repository to quotes view model Factory and we are done here by now you have already created everything except for the view which the user can interact with so let's go over to quotes activity and start writing code there we're gonna create a new function private fun initialize UI and we are going to call it from an create so initialize UI inside this initialize UI we're gonna get the quotes view model factory from the injector utils so valve factory cause we model factory will be gotten from injector you tells that provide quotes view model factory and all of the dependencies are created an injector utils so we don't need to worry about anything so now we want to get the view model for our quotes activity so we are gonna create a Val view model and we are gonna get it from view model providers providers of this quotes activity and we want to also supply the factory so that it can be instantiated properly with the repository present in the quotes view model and then we're going to get the view model for model class of quotes view model class Java so basically we are asking the view model provider to provide us with already present or actually instantiate if it's not present quotes view model for us with this Factory now we are going to finally observe live data from the quotes view model so we are going to write view model that get quotes and we want to observe and the owner lifecycle owner is this activity so once it's really destroyed for good the observation will stop that's the advantage of live data you don't need to check the lifecycle yourself you just pass it in and then the live data library will do all of the work for you and then we want to create an observer so this will get quotes list so we want to pass it inside the observer and we are gonna instantiate a string builder so stringbuilder instance and then for each quote we want to append the contents of the quote to the stringbuilder so stringbuilder that append and we want to append a new string interpolate it so it will contain quote and then two new lines so that we have some spacing between all of the quotes and then we finally want to set the textview oh it's text so text we call its text to be equal to the string builder convert it to a string and then also when the button is clicked we want to instantiate a quote and add it to the database through the view model so we are going to get the button the single button button in our activity and we want to set its on click listener and over here we want to create a new instance of quote so quote and it's going to contain the contents of the edit text quote that text that to string and also add a text author that text that to to string and then finally we want to add this quote through the view model which will subsequently pass it to the database so we want to call view model that add quote and we want to add the quote which we have just instantiate it and then we want to get edit text quote and set its text so set text to be an empty string and then we can copy this build oh so ctrl d and we are going to also set the text to be empty on the edit text author so this is it now let's run it on an emulator and here we so let's put a silly quote over here quotes are cool Einstein and let's hit add quote button it's gonna be added over there and when we rotate the device because it's in the Dow it's actually not going to be destroyed we can add a new quote next a done so add quote and it's also present in there so everything seems to be working properly and that's it for this tutorial if you want to learn from the written version of this tutorial you can do so from the link in the video description where there is a post on reso coder com if you don't want to miss more tutorials like this also once where we are gonna be building a real app subscribe to this channel and also hit the bell button so that you are gonna be notified about all of my new videos if this video helped you to understand how to implement model view viewmodel inside your android projects give this video a like and also share it leave a comment follow me on social media and see you in the next video [Music]
Info
Channel: Reso Coder
Views: 164,344
Rating: 4.8732901 out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, android tutorial, android mvvm, android mvvm tutorial, android mvvm architecture, android mvvm kotlin, android kotlin, android kotlin tutorial, model view viewmodel, model view viewmodel android, android architecture components, android architecture, android architecture components tutorial, android viewmodel, android livedata, android livedata tutorial
Id: d7UxPYxgBoA
Channel Id: undefined
Length: 35min 53sec (2153 seconds)
Published: Fri Sep 07 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.