Kotlin Android Development Course for Beginners // ViewBinding + ViewModel + LiveData // MVVM

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey Deb's and welcome back to week eight of our ongoing Android development course this week we're going to be refactoring forecast details fragment to take advantage of some of the new features coming out of android jetpack we're gonna make use of a view binding to remove all of the calls to find you by ID within that fragment we're gonna make use of the Android architecture component view model to a format and manage our UI data and to persist that data across configuration changes so by the end of this week's assignment you should have a basic implementation of mvvm within your forecast details screen this will demonstrate to you how separating your code into these separate layers can make it smaller easier to work with and more extensible as you were to build this out into a more fully functional app alright let's jump into our lecture for this week we're going to be talking about view binding the Android architecture component view model class and a general mvvm architectural pattern so we'll go over a quick project overview what are we building this week then we'll talk a bit about view binding and how we can use it to replace calls to find view by ID will then introduce the Android architecture component view model and talk a bit about mvvm and how we can use the view model in that architecture and then finally we'll wrap it up with a brief overview of view model scoping and how we can use view model scoping to save data across configuration changes so for our project demo now for the last eight weeks or so this would be the point where I would jump over to the emulator and walk through the new functionality we're adding however this week the app looks pretty much exactly this we're not updating anything to the UI this week all the changes are going to be kind of internal more of how we're structuring our code so this week we're going to be focusing exclusively on refactoring forecast details fragment in a few different ways we're going to use view binding to replace all of our calls to find the view by ID we're going to introduce the Android view model class and use that to implement a simple mvvm architecture within a forecast details fragment and then finally we're gonna save data across configuration changes by using view model scoping and reusing existing view model data when the fragment and the device is doing things like rotating around so let's jump into view binding what exactly is view binding so view binding is really a new feature new functionality within Android really sort of becoming popular in the past year and effectively what view binding does is it's a compiler option that will generate a statically typed view references for us and this essentially removes any need to call find view by ID within an activity or in this case of fragment we can get a reference to a binding class for a particular layout so for our forecast details fragment for example we have a layout called fragment forecast details XML once we've enabled view binding that XML gets converted into a binding class that has a very similar name so instead of fragment forecast details that XML we get a binding class called fragment forecast details binding we can then inflate that binding very similarly to how we would inflate a fragment layout anyway as we call inflate we pass in the layout inflator the parent container and false generally because we don't want to add it parent automatically once we have the binding class this is where the real magic happens any view within the layout XML that has an ID property will have a property added to the generated binding class we can then reference those views using the binding class so in this case we call binding description text to get access to the text view in our fragment layout with the ID of description text and similarly for date text or for the forecast icon and so because we have this generated binding class we don't need to look up the views using find view by ID and where this is really nice is that it gives us compile time safety if for some reason we remove a view but don't update our code we're gonna know about it because it won't compile anymore whereas before if we were using find view by a B that check is done at runtime and it might cause us to crash when we try to inflate that view a trend so now like I mentioned this is all happening with a compiler option essentially that's generating this code for us and we enable that in our apps build.gradle file so within the Android configuration block we add this view binding configuration and set enabled equals to true once you've done that and done a sync and maybe a rebuild on your project when you have layouts it should generate these binding classes for you based on the XML now our next topic for the week is view model specifically the the view model class from the android architecture components and this week we're gonna be looking at how we can use the view model to help us separate business logic from the UI presentation logic within our app now the the kind of official definition of view model I think is actually pretty good here so we're just gonna take a look at that the view model class is designed to store and manage UI related data in a lifecycle conscious way the view model class allows data to survive configuration changes such as screen rotations we're going to look at that example so basically what this is saying is the view model is a good place to basically decide what needs to be on the screen expose that data to your fragment or your activity and then because the view model is responsible for handing out that data that data can then survive configuration changes such as rotating your screen meaning that you don't have to reload data anytime the screen is rotated or any other number of configuration changes happen so this is a really nice win for us because it helps our apps be more efficient require less network usage etc so with the view model we can do a number of things we can use it to manage our data sources it might have multiple repositories and it pulls data in from all of them combines them all together and and then it might format that data so it might take in a date/time stamp and turn that into a displayable date it might build up an icon URL based on some type of code or convention and the API the view model then helps us save data cross configuration changes we can then expose that data to be displayed in the UI using something like live data so that the UI will only be updated when it's active but the view model can update itself independent of needing to know about the fragment and what state it's in now the view model lends itself pretty well to implementing the nvvm architectural pattern now if you aren't familiar mvvm stands for model view viewmodel and it's it's really its goal is to help us separate business logic and UI presentation logic currently we have really all of our logic within the fragment so it means where we're loading some of our data or getting access to the data in the fragment we're then formatting it there and binding it into the UI and in small screens and small projects like ours that's usually not too much of an issue but for larger code bases production code bases that quickly becomes unmanageable and if you want to scale your app properly and have it be maintainable have it be easy to work with it's good to separate that logic out because it gives you clearly defined boundaries as to what types of code to put where it makes it easier to debug issues it makes it easier to add code it's just a good practice all the way around so in mvvm you have these three components you have a view a view model and a model and these are all kind of abstract it's hard to know exactly what's going on here so in our case a little bit more concretely the view layer in our case is going to be the fragment we're gonna work to make the fragment do as little as possible so that the majority of all the the logic and the thinking behind what's gonna go on to the screen is done elsewhere now the view model is the place where that's really gonna happen we're gonna take in the arguments the data that we need format it in the view model and then expose it to the fragment using live data and then and in more complex examples the the model layer that could be everything in like your repositories that could be your your databases your network services all the stuff that is actually fetching the data could be considered in their repositories and so data usually wants to flow between these layers in very distinct ways your view model is likely going to be getting data from the repository and then it's going to expose data to the fragment and now the fragment might need to send events back to the view model like hey I clicked a button and then the view model might need to respond to that by going out to a repository or a service and saying get me some new data or make this network request so the idea here is to give you clearly defined and clearly defined layers with which to structure your code now once you've put all of this new code into your view model we want to make use of view model scoping to make sure that we're reusing data and the reason we want to do this is that we want to avoid creating new view models and thereby loading additional data in response to things like configuration changes now we haven't talked too much about configuration changes in this course but a configuration change is something like a device rotation for example where you're going from portrait mode to landscape mode or maybe vice versa because this might require a new layout to be loaded we get a configuration change and by default a configuration change usually means that the entire activity is destroyed and recreated and thereby fragments destroyed and recreated so if you don't take advantage of you model scoping what will happen is you'll create a new fragment then a new view model for that fragment and you'll load the data all over again if you have expensive data meaning it takes a lot of network bandwidth it takes a lot of database time to load this then becomes really expensive and it's hard to manage and leads to poor user experiences so we want to reuse our existing view models and we can reuse those within a couple different scopes and when I say scope essentially that defines how long the view model will stay active so for example you could define a view model scope that says for as long as this fragment is on the screen this view model will be active or you could say for as long as this activity is is alive we're gonna reuse the same view model so anytime someone asks for a particular type of view model we'll hand back the same one and similarly you could do the same for a navigation graph now like I said what this does for us is it helps our apps be more responsive we make fewer network requests database and an overall better user experience and we're gonna see step-by-step how to combine all of these things to really make our code here easier to manage and more performant you're gonna see that the fragment becomes much less code the view model becomes very clear how it's taking in data and then formatting that and exposing it to the UI and we'll take advantage of view model scoping so that we're not reloading and reformatting data when the device is rotated and so with that we'll go ahead and jump over to Android studio and dive into our code updates for the week okay so we're gonna start off this week by taking advantage of the view binding functionality that has been newly added to Android so to do this we're going to open up our apps build.gradle file now within this we need to configure a build option for our android app so within this bill Gradle file will find the Android block here then we'll scroll down to the bottom in below where we have configured our cutland compiler options we're gonna hit return and we're gonna type view binding followed by an open and closed curly brace and then we're going to type enabled equals true so this should go ahead and enable the view binding compiler option within our project and this is going to generate binding classes for us from our layout files so after we've updated this we're gonna be prompted to sink our Gradle file once again so we'll go ahead and hit sync then we're gonna want to open up forecast details fragment and now this week we're going to be working on refactoring forecast details fragment to take advantage of view binding then after that we're going to refactor this to make use of an mvvm a UI architecture pattern so now that we are in the forecast details fragment we want to make use of the binding class that the view binding compiler option generates for us so to do this we're going to start off by creating a couple new properties to manage our binding class and this is going to follow the pattern very similar to that that we've used for managing live data in some of our repositories we're gonna have a a private internal binding option and then we will have more of the public facing one that we want to be a part of our main API for this class so to start we'll type private VAR underscore binding : now for the type we want to access the binding class that was generated for the fragments layout file so to do that we'll type fragment forecast details binding and then this is going to be a nullable types so we'll add the question mark and then we'll initialize that to a null value now we're going to create the more the non null property that we are going to take advantage of when we want to use the binding in the fragment and so to start we're just going to leave a little comment here this has this property only valid between on create view and on destroy view and we'll talk a little bit more about why we want to add this comment and what it means in a moment so after we've added the comment now we can type private Val binding and now we're going to add a custom getter for this property by type get open and closed paren then an equal sign underscore biting and now we're gonna add a double exclamation point here and the reason for adding the double exclamation point is because it will enforce the type of the binding property to be non null so to illustrate this we'll come back to our our binding here and we're going to once again make use of the fragment forecast details of binding type 1 once we've added that type we'll see that we have this error on the underscore binding assignment this error is basically telling us we have a mismatch it's saying that we have requested a non no binding property but we've passed in a nullable binding property because underscore binding is a null type now as we've pointed out in the comment we want the binding property to be valid only within certain life cycle methods of our fragment because that's when we expect the view to actually be available and be valid so that's why we have these two properties we have the underscore binding that represents the fact that this might be null throughout the entire lifecycle of the fragment and then we have the non null binding property to represent the non null expectation of that property within the oncreateview and ondestroy view lifecycle so to enforce binding being non null we're gonna assign underscore binding and we add SS commission point because that will throw an error if for some reason underscore binding is null at that point so we're just gonna go ahead and remove the explicit type there because it can be inferred automatically now that we have our binding class or our binding property set up we want to actually make you of that binding now ultimately using this binding class is going to let us replace all of our calls to find view by ID within the oncreateview method of our fragment to start we're going to make use of the binding class to replace the call to the layout inflator so we'll come into oncreateview and we're gonna delete the first line here and instead we're gonna update it to a sign underscore by mean equals fragment details binding dot inflate within the inflate call we're then going to pass in the layout inflator the container and we'll pass in false so this actually looks very similar to the way we were inflating the layout before so now this has given us access to our the the binding object we need me to come down to the bottom of oncreateview and instead of returning layout now we're gonna return binding dot route binding dot route is a property available on all the generated view binding classes and route essentially just gives you the route view it returns you back the whole layout so now that we have initialized our binding property within on create view we need to clean it up in ondestroy view so i'm going to hit return a couple times and we're gonna add an implementation of ondestroy view to do that i can simply start typing on destroy and it should give you several methods to choose from so if you select down to on destroy view and hit enter it should generate that implementation for you so now hit enter and below these call to super Don destroy view we're gonna type underscore binding equals no so this will just work to ensure that we are clearing the reference to the binding because we want to the views to be cleaned up in memory when they are destroyed this will help us prevent memory links and help us keep our app performant so now for the fun call in our earth scuse me now for the and now for the fun part of using view binding we're gonna replace all of the calls to find view by ID so I'll simply come up here and then on create you I'm gonna highlight all of those calls to find view by ID and simply delete them now we're gonna have a number of errors here because we're trying to assign data to view elements that no longer exist so you can see here I have a unresolved reference to temp text so the way to fix this is to use our binding property and remember we're gonna use the non null version because within oncreateview until it's destroyed we can expect binding to be not null so I'm going to type binding dot and as soon as I do that the reference resolves so how is this actually working well if we open up our layout fragment forecast details if we look at the XML you'll see here that for each view we have added an ID so if we look specifically at temp text you'll see that we have an ID of temp text if we come back over to our fragment will see that matches exactly the property the binding class so for every xml layout element in your layout the binding class will generate a property as long as that view element has an ID on it so we come back to our fragment we can finish updating these references so I will type of binding dot description text binding dot date text binding dot forecast icon and so now we no longer have any calls to find view by ID and if we deploy our app it should look just the same as it did before so I will quickly enter a zip code click Submit and then I will load up some forecast details and there we go it looks exactly the same as it did before but we have now successfully integrated the view binding library now that we've integrated view binding let's work on implementing an mvvm architectural pattern into our app to do this we're going to make use of the android architecture components view model class the view model will serve as our place for loading data and defining the view state there should be bound to our UI this will help us persist data state across configuration changes such as rotating the device to do this we're going to start by opening up our App level build.gradle file over on the left hand side of the screen we're going to scroll down to the bottom and in the dependency section we're going to enter in right below the navigation dependencies and we're gonna add the dependency for the view model class to do this we'll start by typing then we'll add double quotes and we'll type and write x dot lifecycle : lifecycle - view model - k TX : 2.2 dot 0 now as always after we've added our dependency let's go ahead and do a resync to make sure we have entered the dependency correctly and if the sync it completes we should now be able to make use of the view model class so to do that let's start by opening up our forecast details fragment once again so we're gonna make use of a new view model for forecast details fragment we're gonna use the view model to format our data and it is gonna then expose data using live data and then within the fragment we will observe the live data and update our UI so to start all of this off we're going to come to the project pane on the left-hand side of the screen we're going to right click on the details package go to new cotton file our class then we're going to select class and for a name we're gonna call this forecast details view model and then hit enter now this should generate a class for you and then we're going to extend view model by typing : view model now this should start off as an unresolved type and it should prompt you to import that type to do that we can type alt enter and it should add the proper import for you in just a double check make sure that you have import Android X lifecycle view model at the top of your file now viewmodel has a constructor so we need to go ahead and add open and closed parenthesis and now we have a fully functional although very empty view model now we can go over to our forecast details fragment and underneath our args property we can go ahead and start using the view model by typing private Val view model equals forecast details view model so for now this is just really a placeholder to signify that we will eventually be getting a reference to this view model and using it in the fragment however for now we're gonna go back over to forecast details view model and start working on implementing the the live data that we want to expose that will represent what we want to show on the screen so we're gonna create another class here by once again going to the project pane on the left hand side of the screen selecting details right clicking going to new Kotlin file our class well select a class and this time we're gonna name the class forecast details view state and hit enter we're gonna make this a data class by adding the data modifier at the end and now we're gonna add open and closed parentheses and then we're going to define the fields that we want to store in this forecast details view state this will represent the data that we're altima ting to display on the screen so what data do we want to put in here well if we open up our fragment what data are we setting into the screen we have a temperature value we have a description we have a formatted date and we have an icon URL that's being loaded so those are the values that we're going to add to our view state so we'll start by defining Val temp of type float then we'll add vow description of type string Val date of type string and Val icon URL also of type string and let's go back to forecast details view model and we're gonna make use of this new view state type and we're going to follow the same pattern we've used in our repositories for working with live data so we'll come within the class body and we start off by typing private thou underscore view state : mutable live data once you've typed immutable live data it'll prompt you to add the import you can hit alt enter to automatically add that once again at the top of your file make sure it's imported the proper thing you should see Android X dot lifecycle dot mutable live data now after the mutable live data we have this opening closed angle bracket this is asking us for the type that this live data will expose so this is where we're gonna make use of that new view state Titan forecast details view state so this is signifying that our live data is going to send out new instances of forecast details view state for the fragment to observe and then finally we will initialize this by saying equals mutable live data with an open and closed parenthesis and so now as we've done in our repositories before we're gonna create a public property that mirrors the private one we'll type Val view state : live data and again we'll have to import the live data type here so I'll hit alt enter and it should add the import for Android X dot light cycle dot live data we're also going to expose a forecast details view state and this time we will say equals underscore view state so this will let us configure our state expose it via live data and let the fragment bind it into the UI this keeps a nice separation of concerns between the business logic of formatting and combining data and the UI logic of placing those individual values into the views so now that we have this basic live data setup let's go to the fragment and work on observing this data so to do that we're gonna come down here and right below on create view we're gonna add another fragment life cycle method here we're gonna observe the live data using a lifecycle method called on view created so I type on view created hit enter and it pre-populated this implementation on view created as the name suggest is going to be called the right after on create view so at this point our view will be set up eventually our view model will be all set up and this will be a nice safe place for us to observe changes in the UI and then ultimately update that UI so now we'll come below super on view created and we're start off by creating a live data observer to observe changes in forecast details view state to do that we'll start off by typing Val view state observer equals and now we're going to start typing observer and we want to make sure we're careful here because there are a number of different observer types available we want to make sure that we select the observer coming from Android X lifecycle so for me I've scrolled down to what is the fourth one for me and I hit enter now this type is going to expect a attempt type to indicate we want to listen to forecast details view state so within the angle brackets I'll type forecast details view state and then I'll add open and closed curly braces within the curly braces I want to rename the it parameter so that it's easier to understand that we're working with a view state so after the open curly brace I'll type view state followed by a dash and then a closed angle bracket for our lambda arrow there now within this eventually we're going to update the UI and for now I'm just gonna leave that comment there because we're not quite ready to do this yet now after we've defined our observer we want to actually observe the values to do that we'll type view model dot view state dot observe now we need to pass in a lifecycle owner so we'll do that by typing view lifecycle owner comma and now we can pass in our view state observer so now when on view created is called we will create this new observer and we'll start observing changes to the view state so now the next thing we need to do in the migration to mvvm is to move the business logic of formatting our date from the fragment into the view model to do this we need a way to get the fragment arguments into our view model currently we're calling things like args temp args description using the args property on our fragment if the view model is going to handle the same types of formatting we need to get that data then to the view model now there are a number of ways to do this some that might be considered cleaner code however some of those ways are also a bit more complicated so we're gonna start pretty simple we're going to add a method on our view model called process args so I'll open up our view model class here and I'm going to create this new method by typing fun process args now as a parameter to process args I'm going to create a parameter called args : and I'm going to make it a be of type forecast details fragment args so those are G's that we get from the fragment we're going to then just pass that into this process args method so now within this method we will convert the passed arguments into a formatted view state to start we're going to assign the view state a new to start we're going to assign a new empty view state so we're gonna say underscore view state equals forecast details view state with an open and closed parentheses so now we're going to need to define each of the properties on that data class so to start we're going to use a named parameter syntax here so it's very clear what we're doing so we were gonna assign temp equals args dot temp then we're gonna add a comma then we're going to say description equals args dot description now the next thing we want to do is the date however if you remember in forecast details fragment we're actually doing some formatting of the date we're using this date format class and then we're passing in some extra logic here for it can reverting the date from milliseconds into the proper time so we need to move all of that logic into the view model to start we're going to copy the date format top-level property from forecast details fragment we're then gonna delete it from the fragment and add it back within the forecast details view model file so now we have that format available let's come back to our fragment and we're gonna copy the line here again that is formatting the date so do a copy and then I'm just gonna add that and paste it within our new method here and that's all we need to do for formatting the date it's the same logic it just now lives within the view model and now for our last property on the view state we need to create the icon URL now just like the date we're doing some processing for the icon URL we have this string here that we're passing in to the call to forecast icon dot load so again we're gonna copy this go back to our forecast details view model and then paste that in to the assignment here now we see that we have this error here what is the problem well remember we need to assign the value of the live data as opposed to the whole live data itself so we'll come back to underscore view state and add dot value so now this is saying okay we are creating a new instance of forecast details view state and we want to assign it as the new value for our live data when we do that assignment it will then update the observer and the fragment and that observer can then use that to update the UI so let's go ahead and make that update now we'll go back to forecast details fragment and we're gonna work on moving the logic out of oncreateview and into our observer in on view created so let's come down here to the observer underneath our comment to update the UI and we're gonna start by adding our temperature text so just like before we can type binding dot temp text dot text equals and now we're going to use the view state so we'll get the updated view state by typing view state dot now we want to use the temp however if we just use view state temp we have an error if you say temp is a float whereas temp text is expecting a string so we need to do the same type of formatting that we are doing in on create view so we're gonna come up here and again copy this line this is format temp for display and we're gonna add that down here within our view state observer however instead of passing are exempt we're gonna pass view state temp now for our next a UI element to update we'll type binding dot description text dot text equals view state dot description then we will say binding dot date text equals view state dot date then we'll say binding dot date text dot text equals view state dot dot date and lastly we will load the forecast icon so we'll again use binding dot forecast icon dot and then we will pass in view state dot icon URL now once we've done this we can come back up to on create view and remove these old calls to the binding class and now we'll just go ahead and clean up some of the spacing just to reduce the amount of code we have here and so now let's talk through the flow here again when our fragment is created we're creating a new instance of a forecast details of view model an on create view we're getting a reference to our binding class in on view created we're adding an observer that will listen to changes in view state coming from the view model and then update the UI based on that new view state if we go ahead and rerun this we can now see how this is looking so if we come over to our week tab open up forecast details you'll see that we have an issue here we only see the icon and really the icon is only displaying the placeholder so what is the problem here well if we look at our code we've set everything up to respond to changes in view state however we haven't actually updated our fragment to make use of the process args method that we previously created so what we can do is in our view created after the call to observe we're gonna add view model dot process args and we will pass in the args property of our fragment so now we should get that initial processing which will give us an initial State and we should now see the data in our UI so if we run this one more time now when we go back to our emulator and view details we see the forecast details that we would expect okay so now we've returned back to forecast details fragment here and now we need to take a step back and think about where we're at currently we've moved a lot of the business logic into our view model the view model then is responsible for formatting some of that data and then exposing that back out as a view state and then that gets used to update the UI so this is nice we have a much cleaner separation of concerns the fragment is responsible for binding data the view model is pulling in data and formatting it properly so this is a nice win however we currently have a subtle issue here if we look at our emulator if we were to rotate the device what would end up happening is that we would actually be creating a new view model each and every time we rotate the device this is very not ideal because it means that we are instantiating new objects when we don't need to now in a simple screen this is not really much of an issue however imagine we're in a more complex screen in which you're making Network requests loading from a database or other more intensive actions we wouldn't want to throw away any loaded data if we didn't have to ideally we could reuse the data that we have already loaded or that we are in the process of loading and then rebind that data to the new fragment view when it's recreated on rotation now to actually implement this we can take advantage of something known as view model scoping to avoid recreating our view model within a specific scope so a view model scope basically is this cept of for as long as the fragment is alive we're gonna use the same view model or for as long as the current activity is alive we're going to use the same view model so what this lets us do is persist our data across configuration changes like a device rotation and then reuse the data that has already been loaded and thankfully taking advantage of the scoping is actually quite easy and we're gonna see how to do that right now so if we look at the top of forecast details fragment remember here we previously instantiated our view model by just adding a new property and instantiating it as a new instance of that view model class to tree to update this to take advantage of view model scoping we can make use of a property delegate available within the Android KTX lifecycle functionality for view models so we'll delete the explicit initialization and we're gonna add a colon forecast details view model to specify the type and then we're going to type by view model and now we're gonna be asked to import the view models delegate here so again I'll hit alt enter and now you want to make sure that you have the proper import once again so scroll up to the top and make sure that you see Android X fragment app view models now what's actually happening here well the by keyword here lets us know that we're going to be using a delegate basically a delegate is a software architecture pattern where we're saying we're going to defer some piece of functionality some look we're gonna defer something to this other class so in this case view models is a delegate and if we click into this it's actually some pretty scary-looking code that we're not gonna go too far into but basically at a high level this view models delegate can manage a a producer and a factory for us what those two things are gonna do is essentially hand us back a view model that is automatically saved and cached for us when things like screen rotation happen so all of that to basically say that by adding this by view models delegate we're now not going to create a new instance of our view model every time the screen is rotated so by adding this we're no longer creating a completely new view model every time we create the fragment and every time it is rotated or other configuration changes that might cause the fragment to be recreated so this is a nice win however we're still duplicating a little bit of work if we look at our view model class and we look at our process args function this is still being called every time on view created is called and every time we call process args we're creating a new instance of the view state even if our live data already has a valid view state in our specific example here this is wasteful because we can expect the args to be the same if there's already a live data so we can't have a live data without already processing the args and if we don't expect the arts to change there's really no reason to recreate that to view state for the live data so ultimately this means that if our live data already has a value we can skip updating the live data so if we come in to process arts here we can add a simple check here that says if view state dot value does not equal no return hello hadn't enter just to space it out so now in forecast details fragment if the screen has been rotated which caused our fragment to or go back through its life cycle where once again gonna call process args however because our view model was retained across the configurations change because we're using that by view models delegate our view models view state is already gonna have a value so there's no need for us to create a new one and we'll just skip and the view data will automatically be bound to the screen so to test this out let's go ahead and rerun our app one more time and if we go back to our details and we start rotating our device we see that we are getting data each time on rotation without any issues now let's go back to Android studio now there's one thing I want to point out here which is that this is a pretty specific to our our example the fact that we can get away with this check-in process args ideally the args would actually be passed to the view model constructor and we wouldn't even need this type of process args method and the reason we want to avoid a method like this is it because it introduces this potential for duplication of work it also means that process arts can be called multiple times for multiple locations and really all we want is to say create a view model and here's everything you need to make it work upfront then we don't have to worry about that data changing it's really getting towards the idea of immutability we don't want things to change unexpectedly for us so there's one more change we can make to how we are initializing our view model to help with this process and to do that we're gonna make use of a view model Factory so we're gonna go to the top of our forecast details view model class here we're gonna hit enter a couple times give us some space to work we're gonna create a new class called forecast details view model Factory so add class forecast details view model Factory now within the constructor we're gonna add a property called private Val args : forecast details fragment args so remember we want to be passing these odds into the view model so we're gonna pass them first into the factory and then the factory will use them to create the view model now this forecast details view model Factory will extend view model provider dot Factory now we'll need to make sure we import the view model provider class that should add an import for Android ex-wife cycle dot view model provider at the top of your file and then I will add some open and close curly braces and now to finish out the implementation of this we need to implement a method called create now create is kind of a scary looking method here so I don't want you to worry too much about the details here basically what this is saying is we want to create some type of generic type with this method and so it's up to us to make sure that the type that's being created is specifically our forecast details view model so within this create method we're going to do just that we're going to make sure we can create the proper type and then return that view model if we can so we'll say if model class dot is assignable from forecast details view model : : class dot Java return forecast details view model and then we will pass in the args now we see an error here because we don't currently have a constructor for our view model that takes in the args so let's just quickly add that to the view model we'll come down to forecast details view model we'll add a primary constructor by adding the open and closed parenthesis and we'll type args : forecast details fragment args now we will update the view model to use those ours in just a moment but for now we'll come back up to our Factory and we need to finish this return statement the return statement is expecting a generic type here so we have to do this little trick and add as T after the instantiation of our view model all this is really doing is making this return as a generic type so that this generic factory method is happy like I said don't worry too much about this this is some more advanced stuff but the important part here is that we are calling is assignable from forecast details view model so that makes sure that we can create the view model and once we've checked that we can create it we create a new instance of it and we return it now after the if statement we're going to add a call that basically will throw an exception if the previous statement fails so I'll add throw illegal argument exception and for the message will put unknown view model class so for some reason our factory fails to create the view model we expect we'll get this exception giving us a pretty helpful message that should help us figure out what's going on so now let's make use of this Factory we'll go back to forecast details fragment now let's find our view model property here and we're gonna go to the line above hit enter a couple times and give us some space to work so we're gonna start off by creating a private late init var called view model factory of type forecast details view model Factory now down in oncreate view after we've initialized our binding class we're gonna assign view model Factory by creating a new instance of it so if you model factory equals forecast details view model Factory and we'll pass in the arcs now we'll scroll back up to the top and we can update the initialization of our view model so we'll come towards the top to our buy view models delegate call here within the parentheses for buy view models we're gonna hit enter and we're going to use named parameter syntax to specify a factory producer for that factory producer we're gonna pass in a lambda which we can do by adding an open and close curly brace and within the lambda we're going to simply pass in our view model factory so what this is now done is it's now said that when the buy view models delegate does its magic behind the scenes to create a new instance of our view model it's gonna use our view model Factory to do so so it's still gonna give us the nice caching that we hope so across configuration change but it's now going to be able to pass in the arguments to the constructor of the view model so now we can come back to forecast details view model and we can actually remove the logic here for initializing the view state value we can remove that from process args and now we're gonna create a new emit block now remember in NIT blocks essentially like a constructor so when this view model is run as an it block will be run and when that init block is run we are going to use the args that were passed into the view model to create a forecast details view state and set it into our live data and so now process args is essentially empty and we can just go ahead and remove that and if we go back to our fragment we can remove the one usage of process args and now if we redeploy the app one more time well again see that we see our forecast details and as we rotate the device we still have those nice forecast details so with this you've now implemented a basic mvvm UI architecture into your app using live data and view binding and you've taken advantage of view model scoping to make sure your data is not being reloaded across device configuration changes like a screen rotation this is a big win toward adhering to Android best practices and for just making your apps efficient and responsive for your users
Info
Channel: goobar
Views: 9,744
Rating: undefined out of 5
Keywords: Kotlin Android Development Course for Beginners, android mvvm kotlin, android viewbinding, android viewbinding tutorial, android view binding example, android viewmodel, android viewmodel livedata, android viewmodel viewbinding, livedata, livedata kotlin, livedata and viewmodel android kotlin, android mvvm kotlin tutorial, view binding android studio, view binding android kotlin, viewbinding android kotlin, android development course using kotlin, android livedata
Id: cWEVIOm-ipo
Channel Id: undefined
Length: 64min 28sec (3868 seconds)
Published: Wed Jun 03 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.