MVVM Clean Architecture - How To Structure Android Apps

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hello welcome back everyone to a new video in which we'll be explaining how an mvvm design pattern app is structured so we'll see all the packages we can have in our mvvm app and what goes in each one and explain in each one basically so you could have a better view of how to structure uh your app so that it uses mvvm design pattern uh properly so first of all what is mvvm mvvm is a a design pattern basically that separates an application into three main components model uh and view model and view so let's explain each one of these first of all let's start with the model this one so the model represents the data uh of our application it is responsible of retrieving and storing the data basically from database or an API uh anything that has to do with data we could handle that inside the model uh parts of our mvvm app and then then go into the view or the screen or the user interface what the users basically see and that is uh basically the user interface it's responsible of displaying the data to the user so the data that we we get from the model then it will be displayed here uh of course with the view and uh in the Android it is uh it is an activity or a fragment or a screen in jitpack compos and then the last one is the view model in this one acts basically as a bridge between the two between the view and the model that's why it's called view model it holds all the states of our screen or of our view so things that can change we hold them or we store them inside our uh view model and then uh of course this one provides methods because uh the view model gets the data from the model and then it updates the the the view accordingly to the data and of course since we hold our states our view States inside the view model then uh these states won't be gone during configuration changes because view model does survive configuration changes so if we have some states that we display here like some counter or anything if we rotate our screen then the counter will will still be at the same state as we lift it before rotating the screen uh otherwise if we have that counter directly here in the view then it will be gone and maybe will start over or something like so so that's why we need a view model in our app so what's going on is that the view basically when we want for example to log in then the view send some user actions like clicking on the Lo L button and then the states are of course the email for example and the password and then the view model now connects the model sends the the email and the password and then the model since that's that's data the model sends that email to the and the password to a backend for example or to a database or whatever and then gives us the data we need for example the information of the user after the model gets that data it sends it of course to the view model so it identifies the view model with the new data that we got and then The View model again notifies the view to display that data of the user so that's how we use our view model basically our MVM design pattern basically so let's go to underw studio and then let's start creating the packages we need for our uh mvvm app there's one thing actually I didn't talk about which is there is actually a repository between between the model and the view model so basically we the you could imagine these arrows as a repositories uh and I will explain them while I'm I'm I'm doing this because it won't be so easy for you to understand so now let's start with the data package which is this one the data part of our mvvm app so in our app basically uh we just create a package called Data like this and here we have all uh the data related uh stuff uh but before actually creating it like this we better have for each future have these three things because for example for authentication then we would have a screen a sign in or a login screen and we would of course have a view model for that in the model that conts connects the back end and then for example the homepage in which we might have some data to display then we would have uh different other ones so for each future in our app then we would have uh their own separate packages so in our package rather create future like this and then inside that future we would then have our data package like this so for each future so this is future one and then we might have uh future two let's say like this and then for future so we then have uh other packages that are of course data and view model and of course all these other ones that I explained but uh now for the future one we would have the data package they said in which we would have all the data stuff and the data stuff are May are basically always but not always but all the time you could say often there are two things which are the remote stuff and the local stuff so the remote stuff may be an API or a backend so things that you connect to remotely that are not locally in on the user's device so we would create a package for that called remote like this and here we would have an API for example so you just create a some API a fake API of course like this and that may be an interface and this interface just have a function get for example data like this so this is our API let's suppose it's like this uh we first actually annotate this if we use retrofit but we don't have that just for the Simplicity this is how our API would look like and then if we have some data uh inside our app I mean in locally in our application uh device I'm sorry then we would have a package called you could say local and which would have our room database SQL whatever uh but I'm not going to create that but in here we would have all the data stuff that would be there locally so normally it is room database and here in remote then we have an apepi that connects like to a back end or an API or something so this is the two things we need for our API but let's actually now create a presentation package so you would understand so our presentation package is is actually in which we will have the view and the view model so let's just create it and then I will explain how you can connect then the view model with the with the the data with the data part so here we have a presentation package of course I will give you an example of this so I have some examples uh so in our presentation that wouldn't be inside the data package I'm sorry so this this is the data package it has nothing to do with the presentation package it's a whole different thing so in here we would have then a view model so let's say just a view model like this and that is a class of course this one would normally extend the view model not this one this one from life cycle and then after that we want our view model of course to get the data from the API or from the data package so this is actually uh the thing that I want I want to explain which is the repository The View model does not care where the data comes from so this is why we need a repository The View model shouldn't care whether that data is coming from a database or an API as long as it gets the data then that's okay with the view model uh and that's why we need repositories so how do we then create a repository we first have a domain package so the domain package you could say it's also part of the date sub parts so it would be right here it's called domain because one thing I actually didn't say the model the model is actually also responsible of the business logic like uh like chicken for example if an email is with formatted or something like so then that's where we uh handle those stuff inside the model package and the uh model part basically and the domain package is actually also a part of the data one so in here in our domain the first thing we usually have is a model like this and this model has nothing actually to do with this one so the model here stands for data so both of these are the model both of these are the model part of our app so the things that handle the data but the model here is just a data class so let just create a d data class let's call it uh user for example and that is a data class so in here we just have uh let's say all name of type string like this so in here we would have our model so in this case it's a user and uh and then in our domain package then we will have a repository so now I'm going to explain what a repository is and why we need that so we have a package called repository and then here we then have our repository interface uh I'm going to call it user repository or something so just repository for Simplicity and that is an interface but why is it an interface so as I said uh a repository as I said we could imagine them as uh these arrows and the repository is just responsible of fixing the data for different parts of uh our app so it knows where to get the data whether from an API or a database and then it brings that data to the right to the right place because we can of course use one repository for different parts in our app for different screens then that's why we need that so we get the data with that repository and then repository brings it of course to the right place uh to the view model to the right view model basically that's how it goes and also the repository helps us to be flexible because the repository adapts to changes in the data sources that's why we I use abstraction so we can change from uh from a database to another one with just abstraction without actually without actually affecting the view model or the part that gets that data so we just change the implementation and then the data where it goes to the part that that where it goes actually doesn't is not affected so that's why we need that repository so whether we are getting it from a database or an API then with our repository we can change that whenever we want of course for testing as well and uh if we want to test our app then we would don't want to use a real API or a real database for that but because that's memory consuming and it's just for testing then you don't want to make too many API calls then you use some fake API for that where you just provide some fake data and then you want to for example try something 100 times but still get the same result and with repositories you can do that because they said with abstraction like this it gives us flexibility to switch data sources in in in our real app like this then we use a real apepi in the real database but when testing then we'll use some fake ones so that's these changes in the data sources are really helpful uh and efficient using our uh repository abstraction so now that we created our interface here now we need to create an implementation as I said said you can have more than just one implementation and the implementation goes basically in our the in our data package so right here we want to create another another just package called repository and now in here we have our repositories implementation so just create a class now called repository implementation maybe this one should be called like this and the the reason why I'm actually doing this video because uh I created lately a playlist about uh how to build a movies app and here I'm in YouTube this is the the actual playlist so we have four videos uh and I actually used MVM design Pion so if someone didn't understand what that is and why I use repositories and all the stuff I used in there then I'm creating this video so you would understand why I did that and uh uh how it helps us actually maintain our code and uh maintain readability and DTI stability if if you want to taste our app uh so let's go back now to under studio and uh our implementation of course we just implement the repository and uh maybe I didn't have any function that's why let's say now get I mean fun get data like this and let's suppose this one returns a list of just string or something so let's say a list of or users we already have users but there's actually one thing I wouldn't use user which is the one that I had uh right here in my domain package because this one uh oops this one is actually the one that I'm going to use in my presentation as well so my presentation will get to use this one when trying to display all the data in the UI but I what I would do instead is actually create a dto here so inside my remote so let's say I'm getting the data from an apepi for example then I would have just a data class that oops not a Java one but a cotlin one let's say user d and that is a data class uh which of course just going to have a name type string that is user and the reason why I would do this because for example in our API there might be some N Things if you watch the movies playlist that I did when you get those movies from the API then there are movies without with some missing data so there are movies with no title with no images so these are missing data and I don't want to have that's inside the one that I'm going to use in my in my presentation or in my UI because I want everything to be available there in case it's not then I'm going for example to put some thing like not available or some zero if some number is isn't there or something like so but in here then I would usually have these ones as nullable like this and then I may get them as null values if they don't exist but then when I want to uh pass that to my to my from the data to the view model then I just map that to the map this user d o to the user that I have in here and then and then of course the data the null attributes I will just give them some default values so that's why we would want to do that and uh to transfer those so this one is called user user dto so that's user I mean data uh transfer object and basically you want to transfer this one from this one using a mapper so you would have a mapper right here a mapper package and then we would just create a file called let's say user mapper and that is just a file like this and a mapper is just an extension function basically so how does it go or how does it work let's say now our user our user dto uh it's say to user like this and this of course returns uh this doesn't take anything but this returns our user and then the name is the name and since since this one can be null as so as I said this one can be null if it doesn't exist in the Epi so it's not our issue it's the API issue then we can give it a default value like this so let's say uh not available or something so just not doesn't exist Ora value it just depends on the type of of the attribute that we handle so we transfer this one to our user then then we can use this one in our presentation or in our UI so going back now to our repository then we want to have not the user instead yes the user actually but uh that our API so let's go back to our API this one should return now with say list of our user dto because this these ones can be null that we get from our API now right here we just want to implement that that function and then of course this repository returns let's say this one takes an instance of that API I'm not going to do any depend any dependency injection thing in here so just an instance of that API that we created like this and then let's say return do G data since we need user then we could say map it to to user like this so we mapped what the user D that we get from right here so this user D we map that to our user so a list of our user uh usually we want to do more complex stuff in here like using flows and things like that and use a resource class to handle failures and things like this but I'm just trying to explain now the the the general view of how this would look like so this is now why we need now our our repository implementation and now in our view model what we do is that we we we get an instance of our repository so well now the implementation so let just create now init block here and say repository. get data so we get the data right here uh usually we have suspend functions in here so uh this one may be a suspend function actually like this and then this one as well and then in our view model then we need to create a view model scope launch so inside the cortin because these are these are uh AO operations which take time so we better do this inside the cortin scope so this is how we can get the data from our repository and the good part of this if we want to then test our view model then we just provide a different implementation because when we create now an instance of our view model then of course we uh pass our implementation which is this one because we want to get the data from this API if we get for for example a different data from a different API then we create a different implementation and then we just pass the new implementation which will give us the the data and we we are testing then we want to give a fake repository then a fake repository implementation where we would have a fake API for that so that's why we need repositories and that's why we need abstraction because the the amount of flexibility that it provides for us and then I also said that in our data parts of uh our mvvm app so that data part consist of these two things the the domain and data we would also have our use cases or our business logic that's why we need to have a package here called use case for example and then here all the business logic stuff like chicken if an email is valid or not if a date is valid or not if things that have nothing to do with Android framework basically but just with the cine framework or Java basically so to check just the business logic if we if a user answers a name we want to make sure that that name is at least five five letters long or if a password has a capital letter in the number and some sbol or something we want to that's business logic we want to handle that inside our use case here we would have classes that have operator functions that just operates those business logic stuff so that's goes into the use cases and I'm going to bring now an example so here I have an example for that which is a an app that I'm building and I will share the source code with you once it's finished so it's an open Source app you can see the source code here and let me just close everything here so you be distructor and let's now check our structure of our app so first of all we uh we create an account and authenticate with our app so here I have a separate package for that since it is a future and inside there I have a data package in which I handle all the data stuff that connects to the to the back end for the sending the password and making sure that the our uh authentication is still valid uh and everything has do with that is handled right here as you can see we have a remote that connects to an API and then a repository that checks that signs Us in and out and uh creates for us an account in all these stuff in our repository and then don't worry about this DI package it's it's for dependency injection and I already explained dependency injection in a previous video you can check that it's right here on YouTube uh yes it's right here you can watch this if you don't know what di means so that's for dependency injection and then I also have a domain pack as I said in here I have my user cases in which I just check for if my email is valid if my name is valid if my password is valid so as I said the business logic stuff goes into the use case package and then of course the repository itself so the interface and then the model in which in this case it's just an O request so when we want to request uh creating an account or yeah create an account we need a name and uh and uh an email and a password of course also we want to sign in we need these three things and then for the next one or actually no this one is just a class result that tells us whether we are authorized or not so it's one is a whole different thing and it's just for basically knowing whether we did authenticate or not or something goes wrong uh but let's go to the presentation package in which uh I now have two screens in my app so sign in in the sign app package because each one has a screen and this is the screen this could be anything this could be a fragment or anything basically we just have States so our screen States so here they are so in this case email and the password and whether we are loading or not then these states of course are of this screen and then we have we will have here an event so events that the user can do so the user actions they said let's go back to figma here it said the user actions so sending the user actions it's just an some events that here uh user can change the email can change the password can then click on a button to sign in so these are the events and then the view model receive those events we have a function here who those actions receive those events and then does something according to the event and then after that it updates it updates basically the state so here is update function it updates that state which is just our sign in state and then of course the screen receives those updates uh right here so that's exactly how it is it is simple it's not a complex thing so this is now that for our uh off package so I'm going to show you now a different uh example now here I have another app which is the movies app that I built in the playlist so let's go now to let's say the movie list future so we have a list of movies and inside the data package now we have a new one that I explained basically which is the local one in which we have our database stuff in here uh we just have a database so if we want to have different databases so database for let's say uh different things like TV series if you want to separate those then put those in a different package now I have a movies package in which I have my database and entity and anything has to do with the local stuff basically now in my repository so this is what I was talking about when I said it the view model does not care where that data comes from as long as it gets the data so the view model has a repository instance here and it just gets the data get movie list it doesn't care where it sends what it needs popular movies it needs uh this is the page this is whether we want to get that data for to get that data from remote only this exists here because normally you want to get the data from the database local database unless we passionate we want to get new movies that's why it forces it to get it from a different place but otherwise it doesn't care where that data comes from unless we Pion it because when we Pion it we need to get new movies and new movies aren't there in the database instead they are in the API but in our implementation we have now uh an instance of our API in our data database basically what's going on here simply we try getting the movies from our database and then in case they they don't exist in the database so so this should load from cash uh or should load local movies then we get them from the database unless they don't exist in the database then we get them from our API and then we get the data which is sent to the view model and the view model retrieves the I mean gets that data and displays it in sends it to the UI to display it and I said the only exception here is when we need then the view model needs to tell the repository that it wants actual movies from the API and the good thing in here we don't want to make too many uh API calls when we are testing this that's why we usually create a fake API to get that data or a fake database to get that data so this is the good use of repository and I gu I explained everything you need to know uh about mvvm or how to structure your mvvm app uh to use the the design Pyon which is is of course recommended by Google uh because of the big advantages it gives us and it might sound it might sound complex but once you build an app or two with it it will be very simple and you will find actually that it is really uh making your code organizable uh and testable and of course readable so this is it for this video we explained the mvvm design pattern and how you can structure that in your Android app uh if you like this please subscribe and like this video and don't forget to follow me on Instagram you will find helpful and useful and and development uh content in there see you in another video and bye
Info
Channel: Ahmed Guedmioui
Views: 11,712
Rating: undefined out of 5
Keywords: android studio tutorial for beginners, android studio project, android studio app development, android studio app, android studio app project, kotlin android tutorial, kotlin tutorial, kotlin multiplatform, kotlin full course, jetpack compose tutorial, jetpack compose android, jetpack compose mvvm, jetpack compose state, jetpack compose viewmodel, jetpack compose vs xml, jetpack compose app, api key, jetpack compose animation
Id: LaoYe8biUq4
Channel Id: undefined
Length: 25min 35sec (1535 seconds)
Published: Tue Dec 12 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.