Android Build an MVVM Clean Architecture Order Application - Android Studio Tutorial

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what's up guys and welcome to this video about building a clean architecture mvvm Android application in our example here we will build an order application which contains multiple orders like you can see here on this starting page and when we click on an order then we can see the different items which belong to this order and also get the total amount at the bottom we can also create then new orders by clicking on this plus Floating Action partner then we get a list of deliverers we can also search for a deliverer for example the school stuff provider here when we click on this deliverer we get a to a sectioner where we can select different products like here with the pencil we can click on Plus for three pencils here then we also need a pencil case for example and the school bag and then we can click on this Floating Action button at the bottom right and get a checkout overview which contains all the items we selected and we can then confirm this order and then you can see at the top we have this new order here from our school staff provider let's also check if the school staff provider order contains all the items we have selected we have one pencil case three pencils and one school bag so everything works fine here and I've chosen this example for building a mvvm clean architecture application because it is not that easy it requires a lot of data logic a lot of State Management logic because we have different orders which can contain different products then a product can be can belong to different orders we have also deliverers which has multiple products and also a deliverer belongs to a specific order and you will see this is not that easy but I think such a little bit more complex example will be more realistic to the real world and I think you can learn a lot of stuff here when we build this and we will build this strictly conforming to the clean architecture principles and one thing I would like to mention before we actually start is that we will structure this project as if this would be a multi-module project we will have an order module later and a core module let's take an example of a tab application where you have four different tabs and the first tab would be our order module the second tab for example a deliverer and products module where you can Define deliverers and products and the third tab would be a settings tab or user profile or something like this and so on so you can imagine that this order application here could be also one tab of a bigger application one module of a bigger application and we will also have a core module here but in the example of the tab application this core module could be also used from different or from other tabs and not only from the order tab but of course we need to access the core module from our order module in order to make this work properly this is why we Define the core module here as well all right okay enough talking now let's actually start building the application first of all I would like to go over the dependencies we need for example room database daggerhills and compose navigation let's go to our build.gradle on the root level so on the project level here we need the dagger Hilt dependency and also the dagger Hill plugin because as I already said we use deckahild for dependency injection data and then in our build.gradle for the module we also need the kotlin cap plugin and the dagger Hills plugin as well and down here in the dependency section we need navigation for compose navigation I'm not quite sure if we actually need this icons dependency here but just leave it like this and the dependency injectioner Decker Hill dependency on the module level and of course room database dependencies I will provide this initial setup in my github's repository which is linked down below and of course later when we have finished the application also the finished state of the application all right okay I would like to define the two packages for our modules first so that you get a slide overview and keep track on which module we are currently in let's create a package called call this will be our core module and also a package for our order feature after that I would like to define the room database and all the different entities and the room database will belong to the core module because let's imagine that we not only have our order feature but also a deliverable feature or some kind of order feature and it also needs to access to the database then this wouldn't make sense to define the database inside our order feature we will do this in the core feature because everyone needs to access the database in here we will have a data layer and a local package where we can put the local database logic into in this local package we will have another package for our different entities and we will start with the deliverer entity which will be a data class deliverer entity and yes okay in order to make room aware that this is an entity for the database we need to annotate this with ADD entity and in here we will have a primary key so that the deliverer entity can be identified deliverer ID of type string and we will also have Bell name after that we can create the product entity as well which will be also a data class products entity this will be also annotated with that entity has also a primary key well products ID or type string and then a value name of type string where price per amount of time float so each product has a specific price per amount and it has an additional property belongs to deliverer because each deliverer can have multiple products but each product only belongs to one specific deliverer this is a relation in our database and now things will get a little bit tricky because room is really a pain when it comes to modeling and defining relational database but where room uses sqlite so so this could be implemented a little bit better in my opinion but maybe in the future let's go to our entities package and create kind of a relational data class which combines this relationship we will um call this deliverable with products data objects which will be also a data class and this data class has an embedded annotation well deliverable entity so this will contain our deliverer entity and also we will annotate this with ADD relation let's not forget the comma here then we can import the relational and we have the parent column which will be our deliverer ID and the entity column which will be our belongs to deliverable and then we can Define where the products of type lists of type product entity okay let's go through this again we have our deliverer entity so each deliverer can have multiple products and which products are in this deliverer with product data object is defined here the parent will be our deliverer entity so the deliverer ID which is unique and each product will have a belongs to deliverable property and this belongs to deliverable property will be the different deliverer IDs so each product has an additional field an additional property where which says that it belongs to this specific deliverer ID and so this can be calculated we could have also used the type converter for all the liberal entity to convert the products to a long string chastener and the deliverer entity would then have an additional Fields called products and after we retrieve them we can convert back to objects but I think if we have like 200 products for each deliverer then this is not really clean and we are also dealing with a relational database here so please don't don't use type converters for such a thing this is um no SQL stuff and we are dealing with relational data so let's create another entity class border entity and this will be also annotated with that entity of course also has a primary key order ID of type string well date of type string when the order was actually triggered well deliverable time maybe you wanna say the deliverer I want I want to get this order into month or as fast as possible then a deliverable name normally we would also apply a well belongs to deliverable field here and then we would have the same principle like we have for the product and the deliverer but right now we are only interested in the deliverable name for each order for the sake of Simplicity we need to create another entity as an Associated entity between our order and our product entity that this is a many-to-many relationship which means that each order can obtain multiple products and each product can belong to multiple orders and to specify to model this the right way we need this Associated entity and we will call this order products entity and this will have an entity annotation as well but this time we will have primary Keys which will be an array we will have the order ID and the product ID we also need to make this a data class and the values will be all the ID of type string products ID of type string and we have an additional property here which is the amount now with this primary Keys it gets unique again each order alone wouldn't be unique because it could have multiple products and each product wouldn't also be unique because it could belong to different orders but together they are unique again and we also have an additional property which says then that in this specific order and this specific products we have chosen this specific amount the last data class we need is a kind of the same like we had with our deliverer with products data object here we also need to combine the different entities to an order object to an order entity later which we can then retrieve in our repositories let's create a new data class this will be order with products data so let's call this order with products data object this won't have any annotation above but it has this embedded annotation the first property well order entity like this then we again have the relation annotation for the parent column we have the order ID or the entity column we have the product ID and in this case we also have an Associated class so we can say Associated by Junction order product entity which is our Associated last double double column class and for the property itself we can say well products list of product entity like this but we also need the amounts of each other product combination and now things will get a little bit uh dump in my opinion because this is not supported that well when it comes to Associated class with additional properties in room maybe um they will do this better in the future but right now we need to solve this like this we will have an additional relation annotation for the parent column we will pass order ID and for the entity column we will pass all the ID as well and then we can Define the order products entities property of type list of type all the product entity and this will give us the same list size here like we have in this product section so we can map them together later but this is not that clean but it's the only way I found okay this was the difficult part setting up all the different entities now we can Define the database itself and room build do the rest for us behind the scenes in our local package we will create a class or the database and I think we can also zoom in a little bit so that you can read this better we will annotate this with Edge database the entities will be an array of our defined entities deliverable entity double double colon class or the entity or the product entity and product entity like this let's also format this a little bit for the versioner we will pass one and then room knows which entities we need which entity classes it should Define the order database itself will be an abstract class which inhabits from room database and in here we can then Define abstract functions which will return our Dao objects later but first we need to divide them in our local package we will Define the differential interfaces we will start with the deliverer now we need to annotate this web at dial for room to know that all the deliverer operations on the database are defined inside this interface River has an insert operation the on conflict strategy will be replaced the function will be a suspended functional insert deliverer and this takes a deliverer entity then we will also have a transaction here I explain why we need this after we Define this a query and we will select all from the liberal entity and not this like this and this will be a suspend function as well gets Deliver us and this will return a list of deliverable with products data objects the reason why we need this Edge transaction annotation is because this deliverable with products data object contains different or multiple entities if we have a closer look at this data class it contains the deliverable entity and also a list of product entities so in the background it needs to do two queries to map them together inside this data class and this transaction annotation means that the operational will be automatic so it will only return this list if all the sub queries were actually successful we will have one additional operation which selects a deliverable Name by its ID we will need this query at one specific point later let's define it here select name from deliverer entity where the deliverable idea is equal to the Past deliverer ID and in here we can Define the functioner gets deliverer Name by ID deliverer ID or type string and this will also of course returns a string then we will also have an order down in our local package which will be also an interface don't forget the add now annotation here we have a transaction as well and query select from order entities so get all orders which will be a suspend functioner get order with products and this will return a list of order with products data objects like this because this is also combined return type so we need this Edge transaction again then we have an insert operational the on conflict strategy will be on conflict strategy dot replace suspend functional insert order this will take an order entity the last operation we need to Define is also an insert operation on conflict strategy dot replace again suspend functioner insert order products entities this will be our Associated class we also need to insert this of course to have the different orders with different product amounts and all that stuff this will be all the product entities and takes a list of all the product entity and after that we can go to our local package again and create another interface which will be our product now it's now annotation for this interface we only need to Define two operations the first will be an insert operational on conflict strategy dot replace again this pen functional insert products and this will take a products entity like this and after that we also have a query selects let's import this from product entity well belongs to deliver raw is equal to deliverer ID so we can get specific products for a deliverer later when we wanna see all the products deliverable offers we want to list them then we can use this query this will be a suspend function as well get products for deliverer it takes the deliverable ID of type string and returns a list of product entity all right okay then we can go to our order database and Define the different functions abstract fund order will return all the dial abstract fund products now which will return the product now and Abstract fund deliverable now which will return the deliverable all right okay this was it for the database setup I know a lot of stuff especially with this relationships but in a real world application you also have this kind of relationships in your data model so I think this is fine here let's go to our core module package and in here we will create another package called di for dependency injection because now we will start to set up dagahertz and after this is set up we can finally start with different Data Business logic view models and all that kind of stuff but we need to make dependency injection possible so that we can inject our dependencies inside our humans for example or inside our use cases for that we will create an object this will be called app module in order to make dagger help be aware of our app module we need to annotate this with that module and add install in and we use Singleton components double double column class here because we will provide the dependencies as Singletons in here we can then say add provides add signature and we will first provides our order database for that we need the application context which can be provided by default from dagahertz we don't need to Define this and this will return the all the database and in here we can say return room dot database Builder we will pass the contexts our order database double double colon class.java and the name for the database which we will simply take all the db4 and then we can say dot build and take a hit now knows how to create such an order database then we also want to provide the order dial which we can annotate that provides again at singletoner functioner provides all the dial this will take the order database and since dagger hill now knows how to provide this order database this can be used in here to provide the order down and it will return an order down and we can say return or the database dot or the Dao and the same thing for our deliverer now we can I think simply copy and paste this here and rename this provides deliverer Tau this will also take the order database returns deliverer now and for here we say dot deliverer now and one more time for our products now provide products now this will return the products now and down here all the database dot product now all right okay I think this is a good point to build the project the first time I already did this my build was successful if you are followed along until now then I would suggest you to also build a project to check if everything works properly I think we should finish the core module first before we go to our order feature module because there's not so much left we only need to define a little bit of domain models and the navigation and after that we can go to our order feature module and can then use the core module if we wouldn't finish the core module first we would later need to switch between the two modules which might be a little bit confusing in our core module package we will create another package called domain in the domain package we will create another package called Model where we put in our business logic models which belong to the core module and this is on the one hand our deliverer which will be a data class and on the other hand we will have the products the reason why they are in the core module and not in the order feature module for example is because in the order feature we need access to the deliverers we need to access the deliverer list so that we can list the different deliverers where the user can select one to select the Deliver Us products so also the products are accessed in the order feature and now let's imagine we have another feature called deliverer feature and there you can Define different deliverers different products then you would also need the deliverer and the products there because they can be accessed from different points in our application let's define our deliverer data class Bell deliverer ID of type stream well name of type string and well products of type list of type products then for our product data class we will have a product ID of type string the name of type string and well price per amount of time floats after that we can set up our navigation logic we will create a package called presentation inside our core module and we will create a composable file called navigational this will be a composable navigational in here we will have a nav controller is equal to remember nav controller and also the reason why we put this navigational component inside our core module is because later we could have more modules which also needs to access the navigation and so the navigation belongs to the core module we will have a nav host which takes the nav controller and let's import this nav host and then we can open this and we also need to define a start destination but for that we first need to Define our different screens we can make this a sealed class called screen rods and this takes a well route of type string and in here we will have the different screens defined as objects the first screen will be our order screen inherits from screen routes and the name will be all the screen then we have all the choose deliverer screen where the different deliverers are listed and the user can choose one screen routes and we will name this order choose deliverable screen like this and after that we need one more screen the order choose products screen where the liver is selected and then all the corresponding products are listed and the user can Define how much he wants to buy it also inherits from screen routes and for the name we will say order choose products screen after that we can Define our start destination which will be screen routes dot orderscreen dot route because the first screen we want to show is the order screen then we need to define the different composables which should be used for our screens this will be composable the route will be screen routes dots or the screen dot route and we didn't Define the order screen yet but just let it ride like this order screen this takes the nav controller which will be equal to an F controller before we start with our order screen and the corresponding view model I would like to add another package inside our core module called util and in this new till package we will create then an object called dummy data because we somehow need to get access to different deliverers with different products the application does not have deliverable feature or product features or something like this so we need to insert them manually once so that we can work with this data and Define our different orders this would be just too big for this application this would be then five hours video if we would also have a deliverable feature so let's just Define some dummy data here let's import deliverable and also products and then we can insert some example deliverers and products which we can then use later in our order feature but we already defined all the necessary logic to insert deliverers and products so we can make use of this and you could also expand this example application with more features with a deliverable feature that you can also make the user Define different deliverers with different products but right now we will only focus on their order feature and for the deliverable and products we use this example data of course you don't need to type this off you can just check out my github's repository which is linked down below and copy and paste this dummy data all right okay let's go to our order feature module and create another package called presentation in this presentation package we will both Define our order screen to get rid of this compiler error inside our navigation component all the screen which will be a file compostable and this will be called all the screen and takes an F controller of type nav controller and then after the Imports the arrow should be gone now we can go to our main activity remove the default stuff also this one and invoke the navigation composable and let's start the application the first time to see if we are currently able to launch this without any errors okay cool we don't get any errors but we need to annotate this main activity with Android entry point for that because if we would use inject annotations for dependency injection later then this wouldn't work with this annotation missing let's also quickly create the dagger held application file which is also required in a hilt application this will be a kotlin class called order app for example inherits from application and we annotate this with ADD Android app and the last thing in our manifest we need to Define this application file like this and then the Decker Hill setup is finally finished now let's go back to our order screen and create the corresponding order of your model in our presentation package inside the order module we will create another kotlin class called order viewmodel and this class will be a hilt view model and we can then in checks VR construct the different dependencies because we set up they are hit it properly this allows us to inject all the dependencies we need now in our view model in a very easy and convenient way we can annotate this with add in checked Constructor but right now we don't have any dependencies defined yet which we need in our order view model and later we will have an order repository which gets injected here so let's first Define different state bars and all that kind of stuff we need in such a viewmodel we will have a private late in advance orders of type list of type order and now we need to Define this order data class which is also business logic which are our orders from the business logic so in our other feature let's create a new package called domain and also a package model in this model we will then Define this order data class order like this such an order has an order ID of type string date of type string when the your order was confirmed well deliverable time when the order should be delivered will deliver the name of type string and while valid products of type list of type products like this and the reason why the order domain model is now in the order feature is because I don't have a use case in my mind where the order should actually be used on another place in the application such an order is only used inside our order feature and Deliver Us in products which are defined in our core module can be used on different places in the application in my opinion maybe you have another use case where this order could be also accessed from another point in the application and then this order could be also defined inside the core module back in our order view model we can then import this order from our domain and the reason why this isn't a state and just a list a normal variable is because this will be our single source of true for the state we will Define additional objects because inside this order there are also a lot of products for example and we don't want to have these products in our state for that we go to our presentation package create a new package called state in the state package we will create a data class called order list item and this will represent one item in the order list the user can see at the order overview and this will have different properties than a domain or the object so we should use a state class a separate State class which contains exactly this information which we are actually need for structure order list item and this will be a data class as I already said it has well order ID of type string the deliverable name of type string and also so a total amount of time double because for each order we want to show the compact overview the total amount and the all the dates of type string then back in our order view model we will Define the order list State wow order list by mutable state of and this will be of type list of type order list item and will be an empty list by default because by default we need to fetch the orders first and then we need to map this orders we get from the repository to such an order list and this is why the list is empty by default and gets initialized after this this will be also a private set because this should be only modified inside our viewmodel and then we have also a state bar is order dialog shown because when we click on an order we want to see the detailed view so which products were actually bought in this order and also some additional information for example by mutable state of faults because by default we didn't select an order the user needs to press on an order and this is why this is set to false by default the last state bar we have here is bar clicked order item in case the user clicks on an order item we also need to initialize this State Bar to actually show the corresponding order products and the total amounts the different products around and all the stuff this will be mutable State off other detail list item which we didn't Define yet and this is of type optional because by default there is no selected order item let's also make this a private set and in our state package we will create another data class called order detail list item and this will take an order ID of type string well deliverable name of type string well all the dates and value products of type list of type products list item and we also need to Define this product list item I know these are a lot of data class definitions here for the states but in order to make this clean this is absolutely necessary because if your application grows and you will just use one stage data class to represent your States what the user should see then this can be really messed up if your application grows and you did structure this the right way then you always need to add additional properties if you want to add a new feature and if you define the stata classes for the state exactly like the user actually sees the different properties then this is highly adaptive because if you say I also want to show the orders email address here then you can just add another value below this order ID for example and then you have also an email address and if you just would use one data class then you would blow this up and this data class which would just grow and would be too big to manage anymore later on let's create the product list item in our state package as a data class product list item which will be a data class of course well ID of type string the name of type string this product list item has also a price per amount of type loads well selected amount so how much of this product was selected of type ins we will also have a valid is expanded of type pool we actually don't need this here in our order overview but we can use this product list item later when the user can select different products and select the amount of the different products for a specific order and for that we can use this product list item data class maybe we should have also defined a new data class for that but I think this is fine now otherwise this would be a little bit too big of defining different data classes all right okay back in our order viewmodel we can then import this order detail list item and the arrow is gone when this viewmodel is created we will initialize the different orders we can do this in this init block and then view modelscope.launch okay we don't have access because it needs to inherit from viewmodel and then we get access to the view model scope and in here we can launch the repository request to get the different orders from the database and let's leave this empty for now because we didn't Define the order repository but we will initialize the orders in here and then we have an additional functioner on order clicked so if the user clicks on a specific order then we get the order ID of type string and we can init the order for dialog and pass the order ID we will Define this function soon and we say then is all the dialog shown to true the init order for dialog function will be a private function in an order for dialog and it takes the order ID of type string and now we need to get the order which was actually clicked from the user we can say clicked order item is equal to orders first order and we compare the order ID of the current order inside this orders array to the clicked or the ID and then this will return an order and right now we will get an order back but we want to have an order detailed list item and we need to define a specific mapple function now to map such an order to an order detail list item we can do this in our presentation package there we create another package called mapper and we will do this in the presentation layer because we want to extend the order now the order data class to make this mappable to such an order list item and if we would use this in here for example we say something like this function to order detail list item and we would return an order detail list item then you can see with this import instruction that we are currently accessing the present rotation layer but we are in the domain layer and in terms of clean architecture we aren't allowed to do this and this is why we Define this mapper inside this presentation layer as an extension function let's remove this again also remove this import inside this mapper we will say kotlin file or the web app and we will make this an extension functional so one order to order detail list item returns an order detailed list item and let's import this order now and you can see with the import instruction that we are now accessing the domain layer from our presentation layer but this is fine in clean architecture we are allowed to access the domain layer from our presentation layer but not the other way around and this is why we make this a method function inside the presentation layer in here we can say return order detail list item for the order ID you will pass the order ID for the deliverable name the deliverer name and in such an extension functioner we of course have all the access to the orders property the order dates will be dates and now we also need to insert the products we need the product list item here but right now if we have a look at the products we will have a list of products so we also need to make a map of functional for the domain products to our product list item in the presentation layer and I also need to make a little adjustment in our order domain model class we don't have products here we have bought products because each order has of course bought products and not General products and for that in our model class we also can Define this Bots product domain model bought products this data class will have a product ID of type string a name of type string rise per amount of type loads and an amount of time ins and then in our order domain model we have a list of board products okay all right let's go back to our order mapper here we had the problem that this products now they are bought products don't match with these products which are of type product list item so we need another extensioner functioner inside this mapper package let's create a kotlin file called Product mapper and this time we wanna map a board product to our product list item so functional bought products to products list item and the same principle here we accessing the domain layer because we need to spot products which sits in the domain layer but this is fine since we are in the presentation layer and this will return a product list item return products list item the ID will be product ID name will be name price per amount will be price per amount selected amount will be the amount and this expanded is not needed here so we can just set this to false inside the order mapper we can now map all these products products dot map we get the board product here and we can simply say bot products to product list item all right okay now we have done all this work all this mapping to Simply say got to order detail list item like this and you can see we can make this view modeler very clean with this approach because all the mapping stuff runs behind the scenes in other classes which are responsible only for mapping stuff and we don't need to do this inside our new model the next function in our view model will be on dismiss order dialog so when the user dismisses the detail dialog and goes back to the order overview then we simply say this order dialog shown true false we can also set the clicked order item to null again the last function we need in our order view model will be a private functioner called setup order lists in here we will set up and initialize our order list from the orders which we get from the repository we will first need a formatter for the date time formatting because we want to sort the different orders by date and in the database date is only saved as a string so we first need to convert this string to a date to make the comparison possible date timeformata dot off pattern and I will use this pattern day dot month month year year the hours the minutes and the seconds because I will also save the date later in this format date sorting could be also done in a use case but I'm not that big fan of using use cases when there are just two lines of functionality we will also apply use cases later we have three use case classes in this project to also show you how and where to apply use cases but we won't use a use case for this sorting before we actually come to the Sorting we need another extension mapping function because we also want to map an order to order list item not the order detail list item but the order list item in this case we will return all the list item the order ID will be order ID the deliverer name will be deliverable name the all the dates will be dates and we also need the total amount for that we make a little calculation of products.sum off and here we say it's dot amount multiplied with bits dot price per amount then we will convert this to double and the compiler error is gone back in our order view model we can then start with the mapping of the initial orders to our order list items our order list is equal to orders.map here we get the order then we say order dots to order list item and we will also Source this by descending because we want to have the latest order at the top here we also get access to each order list item here we say local date time dot pass we pass all the list item dot all the dates and our formatter and then this initialize our order lists with all the orders we get from the database from our repository and sorts it by the date up here in our init blog we will get the orders from the order repository here and after that we can say set up order this because then the orders are here inside the orders because we are in the creatine scope the repository function will be suspend function so this will suspend until the orders is initialized and then we can set up the order list okay all right I think it's time to implement this repository so that we can finish this view model we will Define the repositories interface inside the domain package because then our view model does not directly accesses the data layer it's all only accesses the domain layer and the realization of this interface of the order repository will then be Hema inside the data layer so again the data layer access the domain layer and we have all dependencies in the right direction we will create a package inside the domain package called repository inside this repository package we will create our interface called order Repository this repository will have five suspend function the first will be insert order which takes an order the second one will be suspend function get orders which will return a list of order the third one gets Deliver Us will return a list of deliverer and the fourth one get products for deliverer take the deliverable ID of type string and Returns the list of products then the last one will be also of course the suspend function it gets deliverer Name by ID it also takes a deliverer ID of type string and returns a string which will be then the corresponding name and although we are inside the order feature our order module we can access this deliverer and we have also the deliverer logic to get deliverers to get products because we need this in our order feature and this belongs to our order feature even though we need to access the deliverable dial and the product dilator but this is absolutely right to have this logic inside our order feature and therefore we have created this core module where the deliverable and product Logic for data accessing is actually defined okay all right let's implement this repositories interface definition in our order feature we will create a new package called data and another package called repository in this repository we then create a kotlin class called order repository Implement and this will get some in check that Constructor arguments and this will be well ordered our of type order dial our deliverer now and our product our and of course it realizes the order repository we can Implement all the member functions then like this and we built start with the insert order functioner for that we can say order down dot insert order and now we need to map our order to an order entity and we have the same principle here now for order to order entity like we had on the UI where we mapped the order to an order list item for example in our data package we create another package called mapper and we again do this in the data layer because we need to access the domain layer where our order is actually defined if we would Define this mapping inside the domain layer then we would need access to the order entity which is defined in the data layer and this is why we again do this not in the domain layer but in the data layer we will create a kotlin file called Auto mapper in here we will again create an extension function from order to order entity and this will also take a deliverable name of type string and returns an order entity like this let's import this order from the domain module or from the domain layer return or the entity or the order ID we will pass the order ID date will be dates deliverable time will be a deliverable time and deliverable name will be equal to the deliverer name now we can go back to our order repository Implement and can say order.2 order entity and for the deliverable name we simply press order dot deliverer name after that we also need to create the list of the associated class so the many too many relationship Associated class between our products and our order we will say well order products entities is equal to order dot products.map in here we get access to all the board products and we can say order product entity this is our Associated entity order.order ID it also takes the product ID which we will get from the bot products dot product ID and bought products dot amounts after that we can say order down DOT insert other product entities and we pass our order product entities and then they are also saved in the database before we start with the next repository functioner we will create another mapper functioner which will be our order with products data object mapper we will call this order with products data object mapper like this and this won't be a class this will be a file and we will define an extension function order with products data object and this will be a mapper functional to an order this will return an order of course let's import order from our domain layer return order or the order ID we will pass all the entity dot order ID because this order with product data object contains an order entity we can have a look at this an order entity here a product entity and also the associated class or the product entities and we need to kind of map them together to such an order in this mapping function for the dates we will say order entity dot date the deliverable name will be order entity dot deliverer name the deliverable time or the entity dots deliverable time and after that we also need to define or map the products when we have a look at our order with products data object again then we need to know that these two lists kind of belong to each other we will have two equal sized lists with the product entities and the corresponding order product entity so we can make use of this we will say products is equal to our products dot zip and we will sip this with all the product entities so that we get a pair here which belongs to each other and then we will say map and we get a pair as I already said and down here we can map this to a board products and we will say pair dot component number one dot product ID pair dot components number one dot name now dot components number one common compiler price per amount and pair Dodge components number two dots amounts like this back in our order repository implement we can then simply say return order down DOT get order with products dot map it starts to order and now you can see again the huge advantage of this mapper classes because this code is so clean and so easy to read but yes of course you have a lot of objects and you also always need to Define these mapping functions and I hope this does not get boring for you but yeah this is my style when it comes to programming and I have a lot of good experiences with it and I think it also sticks very well or it's really cool to combine this with clean architecture principles then you have a really really clean code structure all right okay the next functioner will be our get deliverers here we can say return deliverer now we actually don't need this sketch Deliverance function yet because we are still defining our order view model but I think let's just finish this repository here in order to make this function work properly we need two additional mappers but I think these are the last ones then we have one map of four products and one mapper for the little Ros and we will do this in the core module because deliverer and product stuff belongs to the core module let's actually create a package inside the data package called mapper inside this package we will create a kotlin file called deliverer mapper we will extend the deliverer entity and we'll Define the mapping functional to deliver raw and here we will pass products a list of products and this will return a deliverer and then we can say return deliverer deliverer ID will be deliverer ID name will be named and the products will be our products and after that we also Define another file products method like this we will extend the product entity and the functional will map a product entity to a product so it Returns the products in here we can return the products for the product ID we will pass the product ID the name will be name and the price per amount will be price per amount okay all right let's go back to our order repository here we can say deliverable dot gets deliverers dot map and we will access it with it you can also name this with this long name but I think it is fine here it's Dodge deliverer entity dot two deliverer and we also need to pass products here and for that we can say it's dot products dot map and in here we get access to the product entity and we will map the product entity to products and then this again looks very clean and very few lines are needed to make this work properly because of our mapper functions down here for the get products for deliverer we can say return product Dow dot get products for deliverer and we pass the deliverer ID and we will map this deliver what do we get here product entity and we will say product entity.2 products for the gets deliverer by name we simply return delivered our DOT gets delivered by name and we will pass this deliverer ID we get passed into all right okay let's close all this different folders and packages and go to our presentation package inside our order module and then we can go to the order view model and finish the order setup we will say orders is equal to or we first need to eject of course our order repository and we will make this a private well and down here we can then say order repository dot get orders okay all right let's go to our all the screen it's time to get also a little bit of a visual feedback here we need the order view model of course which we can get from Hilt view model in the order screen we need a scaffold stage scaffold State because we also have a floating action button and the top bar we can get the scaffold skate from remember scaffold stage then we have a scaffold which takes the scaffold States and it also takes the floating action button which can be defined in this block loading action partner like this we have our own click method which we will Define later and we also have a background color which we will set to Orange and I also forgot to add the different colors let me quickly do this in this UI package in the caller section we will simply add this three colors they are enough here I think you can also choose your own colors or simply copy and paste them back in our order screen we can import the orange color it will simply contain an icon with an image vector let's import Eichner the image Vector will be icons dot default dot adds and we also have a Content description Floating Action partner adds order and the tint of this icon will be white we will also have the top bar which we can Define in this block this will be a top F Bar and we don't need this rose gold we only need the Constructor here we pass the title the text will be order overview the color of this text will be white and we also set the background color of this top bar to Orange and then we can open the scaffold scope first of all let's check if the orderviewmodel that order list is empty because then we don't have any order list items to show and we can show the user a message or text that there are currently no orders this will be a box modifier let's import box first the modifier will fill the max size the content alignment will be alignment Dot Center then we can open the box scope and we simply say there are no orders yet in the else case if there are currently orders to show we will have a lazy column this takes the modifier which will fill the max size the background will be Gray the padding will be 10 DP and we also have a vertical Arrangement byte and Arrangement dot Space by 10dp like this then we can open the lazy list scope and we can then Define the different items we want to show they are coming from our orderviewmodel DOT order lists we will also pass a key because it's always a good practice to pass a key in such a lazy column because then if some items would change the whole list wouldn't be rendered again it will only switch the changed item we get access to our order list items here so we will say order list item and for the key we pass the order list item dot ID because this is unique and I think it's called order ID and I'm not sure why the compiler doesn't recognize this or okay like this we just had to open the lazy lists or the item scope and in here we will have order UI AI list item and this will be a composable we need to Define now we go to our presentation package in the order feature and create a new package called components and in this components package we can create this composable file which will be order UE list item and this will be a composible of course order UI list item I've also inserted all the different compose Imports because then the typing can happen a little bit faster otherwise there would be always an import necessary for different composables this order UI list item will take an order list item of type order list item a modifier which we will set to the default modifier and the root composable here will be a column and this column takes the past modifier the vertical Arrangement will be arrangement.spaced by 10dp the horizontal alignment will be alignment.center horizontally inside this column we will have a role which also takes a modifier the modifier here will fill the max width we also have a vertical alignment alignment.center vertically and the horizontal Arrangement will be Arrangement dot space between so that it pushes the two views inside this row to the left and to the right this will be on the one hand the deliverer name and on the other hand the total amounts then we have the text composable which will take our deliverer name or the list item dot deliverer name the font base will be fontbase dot bold the color will be whites different size will be 20 SP and for the other text we can simply copy this and let's also import the white color and paste it down here and for that we need the total amount of the order we can say percent dot 2f to format this a little bit dot formats and we say order list item dot total amount and we will also attach the Euro sign here or maybe you would use the dollar sign and the rest of the properties remain the same then we have a little divider and the color of this divider will be white and the last thing is a box which also takes the multiplier this modifier holds the max width again the content alignment will be alignments.center after that we can open the box scope and pass the text into all the list item dot or the dates the color will be white again the font size will be 16 SP and then our other UI list item is defined and in this order screen we can then import it for the order list item we simply say it's because it refers to the current order list item and then we also pass a modifier and this modifier will fill the max Smith we will have a clip for the click effect later and also for a little bit of rounded Corners rounded Corner shape NDP then we have a border of 1dp the color of this border will be white and we'll also have a round Corner shape of 10 DP then this will be clickable we will Define The Click logic later or well let's just Define it now because we already defined the function for it in our order view model we Define the on order click and we can pass for the order ID it's dot order ID and we also have a little padding of 15 DP all right okay let's actually try this out if this works so far if it shows the other item in the right way using this order list UI item composable we will insert an example order because right now we can't do this in our app I will show you the example data but it's a good point now to have a look if actually everything works before we start we need to go to our order feature and create a new package called di because we also need a dependency injection module here for our order repository for example we will create an object here and we call this order feature module we annotate this with that module again and add install in Singleton component double double column glass and first of all we need to define the provides single nerve for our order repository functioner provide order repository this takes an order down deliverable dial of type deliverable dial and of course for the order dial we also need to specify the type and let's put this in separate lines and also we have the products now this will return an order Repository and it will achieve this by returning an order repository Implement so our concrete implementation which is behind our order repository interface we will pass the order down the deliverer now and the product now dagger Hill already knows how to write them because we defined this at the beginning in our core module then we can go to our order new model and I've inserted this example data let me also put this in a separate line this is just an order with one single product and we can use our order repository to insert this order so let's quickly run the application the first time and then we will remove this and after that we will uncomment this and we should see this one inserted order alright okay the app launched this is really good because we already accessing the database and nothing crashed there and everything worked so far and now we can and remove this example data or maybe uncommented maybe we use this later again and we uncomment this setup order list and the order initialization then we can launch the application again and have a look if the order gets displayed properly okay cool this looks fine it lists the order the order is also applicable but we don't have the dialog which shows the details of the order yet let's implement this now back in our order screen at the bottom we will have an if condition if or the view model but it's all the dialogue shown and orderviewmodeler Dot clicked order item is not equal to another then we can be sure that we can display this detail clicked order item or the dialog we first need to define the dialog though we make this in the presentational components package and we will create a new package another package a composable file and this will be our order detail dialog will be a composable order detail dialog and I already added all the Imports again to make the typing faster the audit detail dialog takes an on dismiss function which will take nothing and also does not return anything and an order detailed list item of type order detail list item the root composable will be a dialog composable it takes an on dismiss request where we can pass our Lambda function which we get provided above and we also have dialog properties and we say use platform default with and set this to false because then we can expand the dialogue to the whole bit we will only use 95 for that but we will be a little bit more flexible and this is currently an experimental mode but um this is like two years now or something like this I think we can use this here then we will open the dialog we will have the cards with an elevation of 5 DP the shape will be a rounded Corner shape of 15 DP and the card also takes a modifier which will be modifier.filmx with to 95 percent and we can also set the height like this film x height to 80 for example the Border will be 1 DP the color will be orange and the shape will be around the corner shape of 15 DPM that we can open the card block and we will have a column it takes the modifier build max size in this case and the padding will be 15 DP the vertical Arrangement will be arrangement.base between the horizontal alignment will be alignment Dot Center horizontally in this column we will have another column and here we have a text we say all Dot from then we get access to our deliverable name like this the font size will be 25 SP the font weights will be fundwage.bulls text align will be text align dot starts and the modifier will be modifier.filmx with and I think we can then copy and paste this text this time we will have the order dates which will be a little bit more smaller we will say all the detail list item dots all the dates the font size will be 14 we don't have a bold font and we also want to have a little padding to the top with 5tp then we have the divider which takes the modifier and this will be modifier.padding to the top equal to 10 DP after that we have the list of our bot products which will be in a lazy column for the latency columns parameters we say vertical Arrangement Arrangement dot Space by 15 DP and it also takes the modifier and here we say padding top is equal to 15 DP after that we can open the lazy column scope and we again have the items and we will pass the order detail list item dot products or the key we will use the ID of our product list item like this and then we will open the block and we will get the lazy item scope in here we will have a row which takes a modifier it will fill the max with the vertical alignment will be alignment.center vertically again horizontal Arrangement will be Arrangement dot space between so there are two views or multiple views inside this row get pushed to the sides then we will have the text and this text will be our it's dots selected amount and we will also attach this little X and plus it's dot name so we can see we have five times this item for example then we will have another text and we can just copy and paste this we will just have two simple texts here and here we have a formatted text pertense Dot to F so that we get two values after the comma formats and here we say it's dot price per amount multiplied with bits.selected amounts and also we will apply or we will add a little dollar or Euro sign oh sorry um at the end of this text below this lazy list in this column scope I think this is the right place here we will have another column where we show the total amount at the bottom with the little divider we have a vertical Arrangement here Arrangement dot spaced by and DP inside here we will have a divider and a row with a modifier the modifier will fill the max with we have a vertical alignment again alignment.center vertically and the arrangement will be Arrangements dot space between again to push the elements to the left and to the right we will open the row scope then we have the text total sum the font values will be font weights.bulls and I think we can then copy this text and paste it down here and here we need to apply a little calculation with a say percent.2f because we also want to have two decimal places after the comma we will say format other detail list item dot products dot sum of so we need to sum all the products selected amounts with the corresponding price per amount and maybe we should do this in a view model or in a even in a use case or something like this I think for the sake of Simplicity we can do this in this one line of code it's dot selected amount multiplied with its dots price per amount then we also need to converters to a double and after that at the very end we will also attach a little hero sign like this and I think then we can start or invoke this order that dialog composable from our order screen and we can have a look if this is actually working because we are right now having one order in our database which we can click on which we can have a look at the details let's invoke the order detail dialog for the on this Miss functioner we will pass the Define function in our view model or the viewmodeler dot on dismiss order dialog and we also need to pass the order detail list item which we will get from our orderviewmodel DOT clicked order item and we can assert that this is not null because we already checked this here or both all right okay let's launch the application and have a look if the dialog works properly and shows the corresponding details all right okay I already see a mistake we have silver Euro here for this order's total costs but this should be two times one Euro 23 so 2 Euro 46 and when we click on this the dialog opens so this works but we have also a total sum of 0 0 and also no product gets listed so there's something wrong with the products I will have to look into this and see you soon all right okay I'm on the mistake here in our um core module inside the entities package we get the order entity from the database and it also looks for the product ID with this Junction and we didn't Define any products yet I just inserted the order without defining um products so um this will just return to empty lists here and normally in our application when the user selects an a deliverer and then also products then they are also there are already products which can then be referred with this ID but right now we have just inserted an order without any products and any Deliver us so this will just return an empty list but never mind the query works fine it just does not return any products because there aren't any and we have just an order okay let's implement the next screen our order choose deliverer screen where we get a list of deliverers we can also search for them in a search text field and then when we click on a deliverer we get to the next screen where we can select different products of this deliverer in our order feature let's also collapse this a little bit to get a little bit of an overview in our order feature module in the presentation we will create a new kotlin file which will be our order choose deliverable screen this will be a compostable order choose deliverer screen and this takes an F controller and also a view model which we also need to Define but first let's define the navigational in our core module in navigation we will have another composable this composable will be screenroads dot order choose deliverable screen dot route and we will invoke the order choose deliverable screen and pass the nav controller in our order screen we can then go up to our Floating Action partner here in the on click method we will then say netcontroller.navigate screen routes dot order choose deliverer screen dot route like this you can also try this out when we click on this Floating Action button then we navigate to another screen let's define the new model for the screen in our presentation layer in the core module we will create another kotlin class called order choose deliverable view model we will annotate this with at Hilt viewmodel again and we also have dependency and check that values here add a check Constructor for example we have the order repository and we also have two use cases in this view model but we will first Define them and then check them later and let's have a look at the state first we will have private late netwa deliverers of type list of type deliver raw the same principle here the deliverers will be our single source of true and then we can apply search operations and sorting operations on this deliverable list here we have about Deliver us to show by immutable state of type list of type deliverable list item and this will be an empty list by default and we make this a private set and first of all we need to import this mutable state of getter and Setter and we have this deliver our list item which we also need to Define now in our state package so State package create a new data class deliver a list item such an item has just the deliverable ID of type string and the name of pipe string and then we can go back to our viewmodel and import this deliverable list item and provide do we get an error here because of these two brackets in the init lock of this view modeler we can then fetch the deliverers we will again need to inhabit from new model to get also the view model scope of course viewmodelscope.launch and we can say Deliver Us is equal to order repository dot get deliverers and then we can set up delivers to show this will be a private function set up Deliver us to show and in here we will initialize and set up the deliverers depending on the current search query and we also want to sort them and for that we need two additional use cases but before we Define them let's also Define the state variable for the search query while deliverable search query by mutable State org and this is empty by default or an empty string also of course a private set let's define these two use cases in our domain package because a use case is business logic and belongs to The Domain layer in the domain package we will create another package called use case and our first use case will be the filter use case we will say filter lists by name use case and we make this in a generic way because we have products and we have deliverers which can both be sorted by their name and also be filtered by their name we will Define this use case as an operator functioner so that we can later just invoke it like this with these two parentheses this will be an operator functioner and takes a generic type T we also need to say invoke it takes a list of this type t and also a name which is our filter criteria and then it returns a list of type T where T has a specific property or fulfills a specific interface definition we will Define this interface now and I will explain this after we Define this it will make totally sense in our core package in our core module we will go to domain we will define an interface which will be called select and sortable by name and the only thing that this interface requires is a property called name of type string and then we can go to our deliverer and conform to this interface so select and sortable by name and oh I think this is the wrong place we need to put it here and we can then say overwrite value name and then this deliverer conforms to such a selected sortable by name interface and the same thing for our products because we also need this for our products we will say overwrite value name and this then these two data classes conform or realize this interface we can close this again go to our filter by name use case and now we can say where t conforms or realizes this select and sortable by name interface then we can open this and now we can pass lists into this use case let's also put this in a separate file like this and now we can insert lists in this filter list by name use case and we don't need to Define different use cases for the product and for the deliverer we can just use this generic use case we could have also put this generic use case in the core module I think because such a use case could be used everywhere in the app but right now let's just put it inside our order feature module and make use of it there in here we can say return lists dot filter and we get access to each item and since each item conforms to this select and sortable by name protocol or interface we can be sure that this item has a name property of type string we will also make this a lowercase and then we ask or we check if it actually contains our past name which is our filter criteria dot lowercase and this is really cool because we can pass any kind of lists here which conforms which realizes this select and sortable by name interface and this is just the protocol and says okay if you are of type of me then you have the name property and we can be sure that we have a name here and can filter on this name the same principle can be applied for our Second Use case which is our sort list by name use case we will create a new kotlin class inside our use case package called sort list by name use case this will be also an operator functioner the generic type T is defined here in Vogue it takes a list and this list is of type generic type T it returns a list dot pipe T well T realizes the select and sortable by name interface and here we can simply say return list dot sorted by item item dot name after that we need to go to our di module the order feature module to Define how such a use case should be provided because we will inject this inside our view model we will say Edge provides add signal functional provides filter lists by name use case this does not take any parameters it returns a filter list by name use case and we can simply say return filter list by name use case we can copy this and apply the same logic for our source list by name we'll say sorts list by name use case this will return a sort list by name use case and down here we also need to adjust this to sort list by name use case back in our order choose deliverable new model we can then eject all these use cases private well sort list by name use case and private filter list by name use case and then we can go to our setup deliverers to show function and can Define the deliverables to show so Deliver us to show is equal to filter list by name use case and we will pass the sort list by name use cases result and we will pass the Deliverance in here and also the deliverable search query and then we get returns a deliverer but we need a deliverer list item so we also need to map this here we get access to the deliverer and in here we need to say deliverer to deliverer list item but we first need to Define this mapping functional but this will be a very short mapping function we will go to our mapper package and create a new kotlin file we will call this deliverer mapper and this will be an extension function again function deliverable dot to deliverer list item Returns the deliverer list item and here we simply say return deliverer list item we will pass the deliverable ID and the deliverable name then we can go back to our viewmodler and import this functional and then the arrow is gone and we successfully created this setup Deliver us to show function the last functioner we need in our viewmodel is the on query change functioner we can say functional on query or let's call this on search where we change because this can be called from our screen when we detect in our Lambda functioner from the text field a new search query input we will get a new value of type string after that we will say deliverable search query is equal to this new value and we can invoke the setup deliverers to show function again and then this gets triggered each time the search query actually changes all right very cool now let's go to our order choose deliverer screen we need the viewmodel here Order choose deliver our new model which we can get from here to your modeler in here we need again the scaffold State well scaffold State because we want to show a top bar remember scaffold State here then our root compostable will be of course a scaffold this scaffold takes the scaffold stage let's import the scaffold the top bar will be inside this block we will have a top app bar and we only need the parameter list of this top app bar again we will pass the title which will be a text also import text deliverer selection like this and the color will be white and also the background color here will be set to Orange in the scaffold we will have a column which takes the modifier this modifier fills the max size the background will be gray again and the padding will be 15 DP also we have vertical Arrangement arrangements.spaced by 10dp so it's import gray and the horizontal alignment will be Center horizontally then we can open the column scope and first we will have a text field at the top where the user can actually insert search queries for different deliverables the value will come from our order choose deliverer view model deliverable search query and for the on value change Lambda functioner we will pass all the choose deliverer view model on deliverable search query on search query chain like this and then we simply pass it for the colors we will say colors is equal to text Fields defaults dot text field colors we will set the background color to whites the text color to gray the cursor color to Orange the focus label color also to Orange and still focused indicator color to Orange as well then we also have a label which will be a text search deliverable and we have a Max lines property set to one below our text field we will have a lazy column with a vertical Arrangements of space by 10 and the multiplier which has a padding of 20 DP then we can open the lazy column scope we have again our items order choose deliverer view model Deliver us to show for the key we have deliverable list item and we take the deliverer list item dot deliverer ID and I'm not quite sure why the compiler support is not that good here before we open this races okay all right never mind in here we will have a deliverer UI list item which we need to Define now the same principle like we had in our order screen we will go to components Define a new content file called the liberal UI list item and this won't be a class this will be a composable level UI list item it takes a deliverer list item and also a modifier which we will set to the default modifier here the root composable will be a row which takes the path modifier and the horizontal Arrangement let's import row firsts will be Arrangement dot space between the vertical alignment will be alignments.center vertically then we can open the row scope we will have a text here deliver a list item dot name color will be set to White let's also Imports the different things and we have an icon which will be a right arrow icon we will have an image Vector this inputs are annoying I icons dot default dot Arrow robot iOS the content description will be error right and the tint will be white as well then we can close this go back and let's import this for the list item we will simply press it and then we also need to define the modifier it will fill the max width the clip will be a rounded Corner shape of 10 DP then we have also a border again 1dp color will be white and this will be a rounded Corner shape or 10 DP as well it will be of course clickable we will Define The Click logic later because we then navigate to the next screen and we also need to pass the deliverer ID to get their corresponding products from our database and we also have a padding 15dp like this and I think this should be it for the screen we can actually launch the application to have a look if everything works fine for that let's import some example deliverers and I have created this deliverable feature because this video is already quite long and let's just imagine that we have a separate section in our app where we can insert deliverers and for that we created this deliverer feature I've just defined a repository class here and also repository implementation and some mapper functioner and the corresponding di module for that and so we can just use this deliverable functioner for what time and insertional of example Deliver us we won't need this anymore but this code is also very cool this module if you want to expand the application but right now you don't need to know what's actually going on inside this delivery of future feature we can go to our order view model for example and just quickly inserts or inject this deliverable Repository and in here in our viewmodeler we can comment this out after that we can say deliverable repository dot inserts Deliver Us okay why don't we have this function here okay this is subtype order repository it needs of course to be your type deliverable repository then we can say insert deliverers and take our dummy data dot Deliver us then we will launch this one time to insert some initial deliverers okay the app didn't crash so everything worked fine then we will close the app again remove this and also remove this injection here let's launch the application again and have a look if the Deliverance gets listed properly okay we don't have orders yet this is fine let's click on this Floating Action partner and then you can see we have our three example Deliver us we can also search for computer and then you can see the computer deliverer gets shown as the only deliverer which matches the search query let's try another words School stuff let's okay all right this works fine I think then we can close the app again and I think the padding was a little bit too big on the left and on the right of our deliverer items let's go to the screen and have a look we should only make a padding top of 20 DP here inside our lazy color one last thing I would like to do before we go to the final round our different product selection screen where we can increase the product amount and also get an overview of the selected products and all that stuff is to go to our main activity and in here I will say window dot status bar color is equal to Orange dot to RGB and also we will do this for the window.navigation bar color orange.2 RGB then we get the orange color at the top and at the bottom on the different bars we can launch the application again to show what I mean by this now the the Bottom bar and the top bar is both orange alright okay back in our order feature module we will go to the presentation package and here we will Define the last screen which will be our choose product screen where we can pass a specific deliverer ID and then we get a list of the corresponding products this specific deliverer offers we will call this screen order choose products screen we can also copy this for the composable definition now this will be a compostable then we will paste this name this of course takes an F controller again because after we confirmed an order we will navigate back to our order overview screen then it also takes a deliverable ID of type string which is optional because when we pass arguments in navigation and compose then we are dealing with optional types and here will be also the view model which we still need to Define let's go to our core feature to our core module in the presentation package we will go to the navigation and Define the last composable here we will say composable screen Roots order choose product screen dot route and we also need to pass a parameter here so we can save plus and this parameter will be our deliverer ID then we will invoke the order choose product screen we can pass the nav controller and the deliverer ID then for the nav controller we simply say an F controller and for the deliverer ID we can say it which is a nav backstack entry dot arguments get string deliverer ID and this is not sure that this deliverer ID was actually passed and this is why we get this as an optional or we need to Define this as an optional in our order choose product screen here let's go back to our other feature and in the presentation layer we then start with our viewmodeler for the order choose product screen we will call this viewmodel order choose products viewmodel and this will be a class we also need in check The annotation here because we need a lot of dependencies in here we need to annotate this with adhill to view model and this time we don't forget to inherit from viewmodel in here we will have the private well or the repository as a dependency privateware filter list by name use case private well sorts list by name use case because we also want to filter and sort different names which we will display to the you saw from the specific Deliverance products we will have a private late in advance for the different products which will be a list of product and again we have the single source of group here with our non-states lists of products then we also have a private late in advance the liberal ID which will be the deliverer ID we pass into the screen and in a launched effect we can then set this deliverer ID and start with the inalization we will have the products to show State Val is equal to mutable State list of product list item and this will be empty by default and of course a private set again because we only want to set this inside this order choose products view model then we have an additional list which represents our current selected products were selected products by mutable state of lists product list item and this will be an empty list by default and also a private set let's import the mutable state of the get and set values the reason why we have a mutable State list of here and here a mutable state of type list is because later we will have a news case where we just exchange or remove one item and add an additional item in our list and then their mutable State list of will fire in a lazy column and dismutable state of only files if the whole list object is actually changed then we have a product search query State Bar by mutable State off which is empty empty string by default private set and the last state wall is while is check out dialog shown by a mutable state of faults and of course also private set then we have a public functioner in a product list which we can call from our screen compostable in a launched effects where we actually get the deliverable ID and then we can pass it in here in this in its product list functioner and we can fetch all the corresponding products to this specific deliverer ID we will say viewmodelscope.launch the products will be initialized from our order repository dot get products for deliverable and we will pass the deliverer ID and then we can also say this adds order choose productsviewmodel Dodge deliverer ID is the deliverer ID so we can save this deliverer ID in case we need it later and then we invoke setup products to show functional which we will Define but let's first divide the on product search query change we can say fun on products search query change we will get a new name this will be called from our screen composable in the Lambda function of our text field later then we say product search query is equal to new name and we also call this setup products to show this will be a private bank setup products to show and in this case we will have a little bit of a more complicated function because the user can select the products he can increase and decrease the selection amount and we somehow want to save the states all the time even if the user also filters the products and that the product list gets filtered and a new list gets returns and we want to keep track of the selection of the different products and therefore we need to apply an additional logic first we will have the products to show is equal to filter lists by name use case and in here we will pass the result of the sortless by name use case and we will pass the products and the product search query this time uh this was the same principle like we had for our deliverers and also the mapping function now we will map such a product to the product list item so we need to Define it we can say products.2 products list item so this functional needs to be defined in our mapper we go to product mapper fun products this time we don't have the board products because this is a normal a general product two products list item and this will return a product list item let's also import products we can say return product list item for the ID we will pass the product ID the name will be the name the price per amount will be the price per amount the selected amount will be 0 by default and also the expanded value will be false by default back in our order choose products view model we can import this and we still get an error because it requires a snapshot a state list we could say something like this to mutable State lists and the error would be gone but we also need to add additional logic because we want to save the selection amount States we will say map again and this time we will have a product list item and down here we will have a well selected item is equal to selected products DOT first owner in here we check its.id is equal to product list item.id this will go through our product list and for each product list item it actually checks if it's currently in the selected products array and if this is the case we can say if selected item is not equal to null then we know that it is currently selected and we can return product list item dot copy and we will say selected amount is equal to selected item dot selected amount and if this is not the case then we can just return the product list item itself and down here we can say two mutable statelet and the arrow is gone now we also need a functioner which expands the specific product when the user clicked on it and also collapse it after the user clicks on it again we will make this a public functional because we can invoke this from our composable screen on list item click this will take the product ID of type string in here we will need the index of the corresponding products to this specific product ID and we will Define a private functioner which helps us to determine the index because we also need the index when we have a plus click and the minus click and we always have the same logic here get index of products for a specific product ID of live stream and this will return an integer we can return products to show dot index of firsts we will get access to all the product list items and we can say product list item dot ID is equal to product ID then we can invoke this get index of product and pass the product ID and later on we will use this function two times and we will save a little bit of code here by defining a little helper function back in our onlist item click functioner we will check on the index if it's actually less than zero just to be sure because this can return -1 If the product is not found but this shouldn't happen because otherwise the user couldn't click on such a list item but just to be sure let's check on this index and return if it's less than zero then we will say products to show of this index is equal to products to show of this index.copy we will set the is expanded VAR to not is expanded products to show of index is expanded like this let's define the logic for the plus click so if the user clicks on a plus if the product is currently expanded and then we want to increase the selection amount by one we will call this function on plus click this takes the product ID of type string and again we need the index which we'll get from our helper function and get index of products we will pass the product ID here and also we will make this little index check if it's less than zero then we will simply return then we need the current selection amount which we will get from our products to show of this index dot selected amount then we will increase this amount products to show of this index is equal to products to show of index dot copy the selected amounts will be our current selection amount plus one after that we also need to update our selected products for the confirm order later for the checkout dialog we will say it's current selected amount is equal to zero then we know that the product was not selected yet because the selection amount was Zero then we can say selected products plus equal products to show of our index and if this is not the case if the product was already selected then we also need to update the specific selected products so we will say selected products is equal to selected products.map in here we will check if ID is equal to our product ID then we will say it's dot copy and for the selected amount we will pass it dot selected amount plus one if this is not the case we will simply say it's all right let's take a little recap at this function we will get the index first of the specific product which the user clicked on if this index is less than zero we will return just to be safe and then we get the current selection amount because the product which was clicked is in the products to show of this specific index and this is the property the selected amount property we will update the products to show at the specific index by increasing the selected amount by one but we also have a list which contains all the selected products and we also need to update this list we will check if the current selection amount is equal to zero then the product is not selected yet and we can simply add this to our selected products array if it's already selected so if the current selection amount is one or higher then we need to update the selection the selected products array we will simply say selected products is equal to selected products and this will each time for each product it will go into the cells and it simply returns it but one of these products will match this if conditioner and here we simply copy it and increase the selected amount by one and maybe you are asking yourself why we have two lists here one for the selected products and one for their products to show because for me we have two different states here we have on the one hand the state of the products which should be currently shown and we should also have a separate state which represents our selected products we could also have a product to shown list only and also an additional property which currently is selected and down here or where do we set up the products here with these two use cases you would also have problems because you get a new list back and you can try it out and you will see that um you will face a little bit of problems here then we also need a functioner for the on minus click if the user decreases the selection amount functional on minus click or a specific product ID again we first get the index from our get index of product helper functioner we will pass the product ID again we make sure that the index is not less than zero otherwise we would return and then we get the current selection amount is equal to products to show of this index and here we get the selected amount and the first thing we want to do is to check on this selection amount if it's actually equal to zero because we can't decrease it below zero we will simply return them and just don't do anything the next thing that can happen is if the current selection amount is equal to one because it will decrease then and it will be 0 then and we also need to remove it from our selected products list we will say selected products is equal to selected products dot to mutable lists and then we will set apply remove all well it's dot ID is equal to our products to show of this index dot ID and then it will remove the selected products which amount gets decreased from 1 to 0 and the last thing we need to do is to update our products to show products to show of index is equal to products to show index.copy again selected amount will be equal to our current selection amounts minus one okay guys we almost did it for this view model and after that we will only have UI logic left we will go down to the bottom and we will say fun on checkout click then we will open our checkout dialog we will say is checkout dialog shown is equal to true and we will also have a dismiss functioner on dismiss check out dialog and this will set there is checkout dialog shown states to false the last function we need here is our on by function when the user clicks on the confirm button to actually buy the different products but for that we need an additional use case let's go to our domain package and in here in the use case package we will create a new class which will be a confirm order use case class and this use case takes an injected Constructor argument private well order repository let's also Implement inject Imports this will be a operator function as well invoke this this takes different products of type list of type bot products and it also takes the deliverer ID of type string in here we first need a curating scope which we will get from keratin scope and for the dispatcher we will pass this patches dot IO because we will do an input output operation here then we will have a formatter of type dates time formatter which is equal to dates timeformata dot off pattern day day month month and let's also put this in a separate line so that you can still read this for the year we will have this four wires then the hour the minutes and the seconds below this formatter we will have the date is equal to a formatter DOT format local dates time dot now then we can say coroutinescope.launch and first we need the deliverer name we will have a well deliverable name is equal to order repository dot gets deliverable by I get deliverable Name by ID we will pass our deliverable ID and then we will say order repository dot insert order and the order will be of course of type order let's import this from our domain the order ID will be uuid.randomuid.2 string the date will be our date the deliverable time will be just set to as fast as possible this is just an example property here and it's the deliverable name will be set to our deliverable name and for the products we simply pass our products and then this use case is done and we can go back to our products view model and can Define this on by function first we need to access our confirm order use case which we will also inject VR Constructor up here private well confirm order use case and I'm not sure why this is okay I've called this use class let's rename this to um use case of course like this select all press OK and then also the property names gets updated accordingly in our di module we also need to provide this use case we can say provide confirm order use case it will return this confirm order use case and also down here we make this adjustment and okay this also takes the order repository we can provide it like this and then we are good to go to go back to our view model and go down here to our on by function here we can say confirm order use case selected products.net hit dot two boards products and we also need to Define this mapper function this will be the last method function we actually need and for the deliverable ID we will pass the saved deliverer ID let's go to our mapper folder to our mapper package to the product mapper and here we can Define this mapping of the board product or to of the product list item to the board product actually again we Define an extension functioner this time for the product list item two Bots products and this will of course return about products and we will say return board products for their product ID we will pass the ID the name will be name the price per amount will be set to price per amount and the amounts will be the selected amount then we can go back and import this functionality and then the arrow is gone and we can use this on by functioner okay finally now we have created this viewmodel and we have finished this viewmodel and the last thing we need to do is to set up our UI and then we are good to go and I think we will need another 20 minutes and the video is already like two hours okay I expected it to take around one hour and a half well I think I can do better let's go to our order choose products screen in here we get now access to our order choose product view model which we will get from Hilt viewmodeler and we first start with the launched effects where the key will be true so that this launched effect only gets triggered once on the initial compositioner we will say if deliverable ID is not equal to null because otherwise the color of this composable didn't pass the Demerol ID and only if this is not equal to null we will say order choose products viewmodel dot in its product list and we will pass the deliverer ID again we will have a scaffold state which we will get from remember scaffold State and we invoke the scaffold now and pass the scaffold stage then we will have a top bar again which will be a top add bar and like we had on the last screens we only need the parameter list for the title we will pass a text products sectional and for the color we will pass why it's and let's import this color let's also import the text composable and down here no below this title we can set the background color to Orange then we will also have a floating action button which we can Define in this block Floating Action button this will provide us an on click functioner and we can say order choose products via model dot on checkout click then our checkout dialog should open or at least the State Bar should be updated to make the opening possible and down here below this curly braces we can set the background color to Orange and in this curly braces we can Define the icon which The Floating Action buttoner should actually contain we will say icon for the image Vector we will press icons dot default dot price check the content description will be that money the tints will be whites the modifier will be a modifier and the size will be defined 32 DP let's also import DP and this should be it then we can go to this parenthesis and open the scaffold scope we will start with a column this column takes the modifier which fills the max size sets the background to Gray and also applies a little padding of 15 degree the vertical Arrangement will be Arrangement dot spaced by NDP the horizontal alignment will be set to alignment Dot Center horizontally now in here we will first start with our text field again so that we can search for different products this will be a text field the value will be our order choose products viewmodel dot product search query then we also have the on value change functioner Lambda function order choose products viewmodel dots on product search query change and we will pass it then we also Define the colors text Fields defaults dot text field colors for the background we say white or the text color we say gray the cursor color will be orange I think we would be faster if we copy and paste this from our previous screen but never mind the focused label color will be also orange and the focused indicator color will be orange as well the label will be of type texts and we say search products and we also set the max line properties to one again below this text field we will have a lazy column the vertical Arrangement will be Arrangement dot space dot NDP the modifier will be set to modifier dot padding top is equal to 20 DP then we can open this lazy column scope again we have this items and we will pass the order choose products viewmodel Dodge products to show for the key we will pass the product list items ID like this like we had in the last screen we will have a specific UI list item here we will call this products UI list item and we first need to Define it inside the components here we will create a new kotlin file called Product UI list item this will be of course a composable products UI list item this composable takes a product list item also the value is expanded of type Boolean on plus click which does not take anything and does not return anything on minus click which also is a Lambda function and does not take and return anything and also a modifier which will be set to the default modifier for the root composable we will have a column which takes the modifier the vertical Arrangement will be Arrangement dot Space by 10 EP and the horizontal alignment will be alignments.center horizontally in here we will have the row now which also takes the modifier and this will fill the max width the horizontal Arrangement will be Arrangement dot space between so that everything what's inside this row gets pushed to the left and the right and the vertical alignment will be alignment Dot Center vertically then we can open the row scope and in here we will have another column and this also takes a vertical Arrangement and this Arrangement will be spaced by 5tp and the horizontal alignment will be alignment dot starts and you will see what this rows and columns are all about in our UI first of all we will have the texts which contains our product list item dot name the color of this text will be white the font weight will be bolds let's also import white and then we can copy this text and paste it down here the second text will be a formatted text so we will say percent Dot 2f dot formats and here we say product list item dot price per amount and then we attach the Euro sign remove this font weight dot bold and instead set the font size to 14 SP so these two texts are basically our product name and below the price per amount below this column we will have an animated visibility which rigors when the product list item dot selected amount is greater than zero then we want to show a row with a horizontal Arrangement which will be Arrangement dot Space by 5.0p the vertical alignment will be alignments.center vertically and in here we will have a check mark and the corresponding selection amount of the selected item we will have an icon the image Vector will be icons dot default dot check the content description will be simply check mark the tins will be white and again we have a text products list item dot selected amount and we also attach this x here so that we can see that it's x times the selected amount the color of this text will be white below this row scope we will have another animated visibility and this triggers if there is expanded Boolean is actually true then we will have a divider the color will be white and we will have a row which takes the modifier the modifier will fill the max with the vertical alignment will be alignments.center vertically the horizontal Arrangement will be Arrangement dot spaced by 25 DP inside this row we will have our two icon buttons for the plus and for the minus we will have an icon button on click method will be simply there to invoke our on minus click after that we can open the icon buttons scope and here we have an icon the image Vector will be items dot default dot remove the contents description will be minus The Tint will be whites then we can copy this icon button and we also need to invoke this on minus click function in here and here we will invoke the on plus click functioner for the icon we have the ads and also the content description will be plus the tint remains white all right okay then we can close this go back to our order choose product screen and import this composable for the parameters we will start with the product list item which will simply be it the modifier will be modifier.filmx with the clip will be a rounded Corner shape with 10 DP the Border will be set to 1 DP the color will be white also rounded Corner shape 10 DP then this is of course clickable for the click effect we will say order choose productsviewmodel dot on list item click and we will pass it dot ID and now you can also read it we will also have a little padding of 10 DP and below this modifier we will Define there is expanded property which will be of its dot is expanded on minus click will be set to order choose productsviewmodel dot or minus click and we will pass it dot ID again the same thing for on plus click or the choose products viewmodeler dots on plus click and we will pass it dot ID and this should be it for this list and now it's time to try this out I will expand this and let's click on this Floating Action button and select the computer hardware store okay nothing happens all right okay because the order choose the liver or screen does not have the navigation logic yet and we didn't Define this in here in this clickable deliverer UI list item function let's close the emulator first um navcontroller dot navigate greenroots dot order choose products screen dot route plus forward slash it's dot deliverer ID and I think yes you can see this we can try this out now we can start the application let's also expand this a little bit so that you can see the floating action button I will click on plus now and select the computer hardware store and as you can see there are different products we can also click on them and then the product expands and shows the minus and plus partner we can also click on them and then we get this selection information how much products we actually selected we can also search for product let's search for Ram and then you can see the selection amount remains we can also search for something else for the Intel processor go back and then you can still see that our selected items have or keep their states all right okay this looks very good so far the last thing we need is when we click on this Floating Action button at the top right then our checkout dialog should show and we should press on confirm to actually confirm such an order all right okay let's close all the files above that things get a little bit more clear and we don't be confused in our order choose product screen we need to invoke this dialog but first we need to Define it in the presentation layer in our components package we will create a new kotlin class called check out dialog this will be a file not a Class A composable check out the dialog this checkout dialog takes two Lambda functions on the one hand on this Miss which does not return anything and also does not take anything then the on confirm Lambda function which also does not take anything and does not return anything and the selected products we want to show of type list of type products list item then we can start by defining the dialog composable this dialog composable first takes the on dismiss request where we simply invoke our on dismiss function then it also also has dialog properties which we will use again to make the dialogue more flexible like we had on the other dialog dialog properties the use platform default with will be set to false and we again need to annotate this with experimental because it's still in the experimental mode in the dialog we will have a cards with the elevation will be 5 DP the shape will be rounded Corner shape 15 DP this card will also take a modifier filmax with 95 percent and film X Heights eighty percent the Border will be 1 DP the color will be um orange the shape will be rounded Corner shape 15 DP then we can open this scope first we will have a column takes the modifier modifier dot filmex size the padding will be 15 DP vertical Arrangement will be arrangements.space between the horizontal alignment will be as alignments.center horizontally then we will have another column this column takes the text the text will be the checkout text the font size will be 25 SP the font weight will be fontbase dot bold the text alignment will be texttheline.start and the modifier will be set to modifier dot fill next with below this text we will have a divider and this takes a modifier as well modifier dot padding n dot DP then we will have an if conditioner which checks if we have already selected products or if there are no products selected products dot is not empty then we can show The Lazy column and also the two buttons for the confirming and for the dismissing the dialog this will be a lazy column as the top composable and the vertical Arrangement will be Arrangement dot Space by 15dp the modifier will be equal to modifier dot padding top is equal to 15 DP then we can open the lazy column scope and for the items we will pass the selected products and the key will be set to product list item product list item dot ID and we can open these items and the compiler arrow is gone for each product we will have a row item this takes the modifier modifier.filmax with the vertical alignment will be alignment Dot Center vertically the horizontal Arrangement will be arrangements.spaced by so each selected product name and the price gets pushed to the left and to the right in this row we will have two simple texts the first text will be at it's dot selected amount times and plus our it's dot name the second text will be a formatted text percent.2f Dot formats price per amount it's dot price per amount multiplied with its dot selected amount and I here you can still see this and then we will say Plus and attach a Euro sign here in the else case if we have no products then we will have a box modifier is equal to modifier dot filmex size the content alignment will be alignments.center and we will display a text to the user please select items to order and since this box fills the max size it will also go over our buttons later and you won't see the buttons anymore but we can also disable them depending on the current selected products item size below this else parentheses we will take this parenthesis and on the line of this parentheses we will Define another column the vertical Arrangement will be Arrangement dot spaced by 10.dp then we will open the column scope we will have the divider this is for the bottom section of our checkout view of our checkout dialog the device provider won't take any arguments then we will have a row the modifier will be set to modifier dot filmex width the vertical alignment will be alignment Dot Center vertically the horizontal Arrangement will be Arrangement dot space between and then we have a text total sum the font weights will be font weights dots bold then we have another text which will be a formatted text percent.2f dot format selected products dot sum of bits dot selected amount multiplied with its dot price per amount and then we convert this to double and at the end we will say plus Euro and attach a Euro sign okay let's go back here and also Define the font weights font weights dots bolts below this row we will have another row which takes the modifier and this row fills the max width of cost and it contains the cancel and the confirmation button the horizontal Arrangement will be Arrangement dot spaced by 30 DP the vertical alignment will be alignment Dot Center vertically then we can open the row scope and Define a button here this button has an on click method where we simply invoke our past on this misfunctional the colors will be set to button defaults and Dodge button colors for the background color we say orange the content color will be white the modifier will be modifier.filmax with and the weights will be set to 1f because on the other button we will also set the weight to 1f and then they share the space of this Row the shape will be a circle shape and we also have a text for this partner text will be a cancel the font weights will be fontways.bolds the text align will be text align Dot Center let's copy this partner and paste it down below we just need to update this to on confirm and this will be also confirm the text of this partner and the rest Remains the Same I think now we can go to our order choose product screen and Define the logic for showing this dialog and then we are good to go to actually start the application and I also think we have finished everything then if order choose products we order please check out dialog shown then we will show the dialog of course check out dialog let's also rearrange this a little bit all those functions and parameters for the on dismiss function we will say all the truth products viewmodel dot on dismiss checkouts dialog or the on confirm functioner we will of course invoke our order choose products V model dot on Buy for the selected products we will pass order choose productsviewmodel.selected products and we also wanna close we also want to navigate back to our order view if we trigger an order so we will also say navcontroller dot navigate screenroots dot order screen dot route and we will also say pop up to zero so that the user can't navigate back all right okay let's try this out and I hope everything works so far let's click on the uploading action partner select the computer hardware store then we for example choose this item this item also the 64 gigabyte RAM and we will have a look at the checkout dialog and the checkout dialog looks kinda good and now we will click on the confirm button and okay this looks fine we are back in our order overview we will see or we can see this computer hardware store order when we click on it then we also see the different items and this is a little bit confusing now with this two times two times but the product's name itself is 2 times 16 gigabyte RAM for example and we selected the specific item two times but yeah I think everything works quite good um we could of course test this further if uh really everything works but on the first view I think this looks fine and the app is kind of finished so far all right okay I hope you enjoyed this video and it was not too long and I also hope that you get more confident now building uh bigger applications with a lot of data and state logic and yeah we will see us in the next video
Info
Channel: K Apps
Views: 5,185
Rating: undefined out of 5
Keywords: Android, Android State Management, Android Jetpack Compose, Android Compose, Android Multi Module Architecture, Android Multi Module, Jetpack Compose StateManagement, Android Dagger Hilt, Android Room Database, Android Relational Database, Android MVVM, Clean Architecture, Android Best Practices, Android Clean Architecture App, Jetpack Compose Clean Architecture, Jetpack Compose MVVM, Android JetpackCompose, Jetpack Compose State Management, Android Clean Architecture
Id: MzWX0gyEUiY
Channel Id: undefined
Length: 139min 18sec (8358 seconds)
Published: Fri Nov 18 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.