Building a Shopping List App: Data Layer Setup using Jetpack Compose and Room Database

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
you're ready to take your underdevelopment skills to the next level Bend you in the right place in this tutorial series we are going to show you step by step how to build a powerful and efficient shopping list app using the latest tools and techniques in Android development we'll be using Japan compose and room database to create a beautiful UI store and retrieve data and connect it all together this is not your average tutorial we are going to dive deep into the code and give you an in-depth understanding of how everything works so whether you're a beginner or an experienced developer this tutorial is for you so Post in your seat belt and let's get started okay so now we want to start to write our code so the first thing here we want to create a new package so you can navigate here to totally new and select here package and we want to create a new package that is called Data so this one is going to help us to organize our codes and files in a place where we're going to get our data so we can create another package and we want to create this package to be a local database or you can just call this room so that we can easily understand that we have a package where we have our data rising from room databases okay so the next thing here we want to create our models so we can just easily select here new and create a new package and call this model and basically let's create here a new putting class or file and we want to call this model okay so now we want to create our tables where we're going to store our data so the first case here we want to create a data class that is going to represent the shopping list so for example here we can easily call this data class and basically we don't want to call these modules so we want to call this for example shopping list and basically here we want to provide the variables or properties which we want them so for example here we want to be this ID and we can just provide this to be an INT so the first case we have to annotate this class with that entity so that we can tell room hey this is just going to be a table inside our database so just create the implementation for it so we can just annotate this with entity and for example here we can provide the table name so let's call this table name and basically we can just rename to whatever we want so for case we're just going to call this shopping list okay so we want also to make this to be primary key so a primary key is just something that is going to identify every item inside our table so we have rows and columns so every row has a unique ID that is going to represent This Record inside this table so that we can easily access it and we have to tell room database to store this to be as a primary key and for case our ID is going to be our primary key so we're going to have a lot of data classes so we want to rename this ID to match our shopping list for example so we can use at column info to tell room database to rename this variable when it's going to store it inside our database so we can just call this column info and basically we want to rename this so we can provide here the name then for example you can just call this list ID and basically it's going to store this as an ID okay so another thing which we want to store here is a name so we can just call this name of that particular item let's add here a comma first this is just going to be of type string okay so before we start to write the other model classes we have first to understand the relational database design because sqlite is just a relational database design and we are going to use this inside our application so let's jump here and see what is a relational database design now let's speak about relational database so a relational database design is the method of organizing data in database using tables and relationships between them so the main idea behind relational database is that the data is stored in Separate Tables and those tables are linked together using relationships which allows the data to be accessed and manipulated in a structured and efficient way so we can have data in different tables but we can easily join them and use them when we want to organize our data so in a relational database data is organized into tables also known as relations so each table has a set of columns and rows and each row represents a single record in the table so for example here we have the ID which is denoted as the primary key so the primary key is just a unique identifier of each record which we insert so every row is just like like a new record inside our database and this ID is going to represent that this is just going to be a unique identifier of that particular record so there are three main types of relationships that can be established between tables one to one one-to-many and many to many now let's look at each particular one so we have a one-to-one relation so a one-to-one relationship is where one record in one table correspond to one and only one record in another table so for example here we have two tables so we have a customer and their address and we want that only a single customer can have this the same address not two customers having the same addresses so how can we do this basically we have to introduce a new item inside our customer table which is just the address ID which is going to be stored inside here and this is just a foreign key so a foreign key is just a column or a set of columns that are going to uniquely identify an item in another table so for example this is going to directly point to the primary key of this address here and basically we are going to store it inside our customer table so that when we want to get this data we can easily just fetch the primary key and then we can join these tables and use them so this is just called the one-to-one relation and also we have the one to many so a one-to-many is a relationship where one record in one table corresponds to many records in another table so for example here we have the items and the shopping list so here for example import the shopping list table is going to have a single item that corresponds to many items that are going to be there so for example you have a shopping list category of for example fruits so here we can have bananas we can have for example mangoes and other things that correspond to the same category but there are just many so here we have one category and here we have many items so this is just one too many and basically for this case we have also to store the shopping list ID which is just the foreign key and we can easily just map this so whenever we find this ID here then we can just join these two tables and have the data inside our our application and also we have the last one which is just many too many so many to many relationship is here where many records in one table correspond to many records in another table so this type of relationship is usually resolved by creating a joint table with the foreign keys of both tables so when you look closely here you can see we have a shopping list and also a customer and another table that is just called the customer shopping list join and basically here we have two primary keys from each table and basically here we have a one to many and here a one to many so basically this is just going to point one here and one to here so whenever we want to create this many to many it's just for example we have a lot of customers having different types of shopping list and basically here we can easily join these two tables now let's finish to create other tables so the second table which you want to create here is the items so we can just easily create here identity and we can just call this to be table name and rename these to be items now let's create here our data class and we can just call this item and now you want to create our ID so we can just easily create here column info and rename the name here to use as the item ID and we want to make this to be a primary key for this item and basically now we want to create our ID and just call here ID to be of type int and we want to make this primary key to be Auto generating whenever we insert a new record so how can we do this basically we can just tell room hey how to generate this particular item and basically here we can just make this to be zero so that whenever we create the item class we do not have to pass this ID here so we have to provide this default implementation also we can create other variables so for example item name this is just going to be of type screen also we want to get the quantity okay so now we want to join between these two tables and earlier we say that we can easily do this by providing the primary key inside for example this table here we want to join between this item table and the shopping list table so how can we do this basically we can use the primary key of this item inside here so let's save here our list ID so we can create a variable and call this list ID and basically this is just going to be the foreign key and this is going to be of type int also we want to create the link between the items and the stores which we are going to purchase them so for this case we can create another following key so for example this is just going to be the store ID foreign key so this is just the foreign key of the table which we have not created and we are going to create in just a moment so this is just going to be of type int and also we want to save the date and also we want to store if this is going to be checked or not so we can just call this is checked and basically this is just going to be of type Boolean so now let's create the store table now let's create a new data class here and we can just call this store table okay we have to annotate this with at entity you can just rename these two stores okay now let's provide here the variables so we want to provide the ID and also we want this to be Auto generated so we can just provide here for example at column info and also we can just provide this to be the primary key and we want to set the auto generate to true okay also we want to join between the store and the list table so we can easily introduce here the list ID foreign key this is just going to be of type int so whenever we store this table here we're going to also to store the reference of this primary key here so whenever we want to get the shopping list and the stores we can easily just use the join between these two variables we have finished to create our data classes and entities so now let's create our data access objects which are just methods which are going to help us to interact with our database so we can perform the crude operations by using dials so now let's jump inside here our room package and now let's create a new putting class or file and basically we want to create a file and call this dial now let's first create the items now so this is just an interface and we can just call this item dial and basically we have to annotate this with at doubt to tell room hey this is just going to be a dial implementation so now when we finish to create that now we can just start to create our methods inside here okay so when we want to perform the crude operation like in setting deleting and other things so we have to perform them here we can create a suspend function and we want to call this inset and basically this is going to help us to insert our item we can just call this item okay so we have to annotate this with at inset to tell room hey create the implementation for inserting the data so when we call this at the inset and we want to provide the uncomfort strategy so for example when we insert an item that has the same the same ID then we have to for example replace or ignore so for a case here we want to replace whenever we provide this so you can just use the uncomfort strategy and call Dot replace so for a case here whenever the items have the same ID they are going to be replaced with a new one okay so we have to create another one which is just add update and here we can just pass in the uncomfort strategy as the stem and create a suspend function and we want to call this update and easily we can just pass in the items and then it's going to update the items okay now we have to add the another annotation which is just at delete and basically we have to provide a suspend function here and call this delete and basically we can just pass in here the items and the items is going to be deleted so as you can see here we are using suspend functions throughout these methods because this method are going to take sometimes a lot of times so we don't want to clock the main UI thread so for this case we have to use another thread in order to execute these methods that's why we are using here for example the Spain functions we never want to delete this okay so the next way here is just to get the items so we can use at query and provide a query statement whenever we want for example to get an item so basically here we can just call here for example add query and inside here now we want to provide the query which we want to get so for example here we want to select and we're going to pass in here the asterisks meaning we want to select everything from the item table okay just call from items and basically it's going to get everything from the item tables now let's pass in here a function and we want to call this code get all items and this one is going to return a flow so we are going to use here a flow so you can use live data and other things so for our case here we want to use a flow and this is just going to be a list of items we want to get every record inside our items so as you can see here we are not using a suspend function because we are using here a floor and flow is just a called item so basically here we never want to use this we have to use a creatine scope in order to consume this data and that's why we are not using here a suspend function okay now let's add another item here to get a specific item so let's add that query and here basically now we have to provide the query so for example you want to select everything from the items and basically now we want to filter here so we want to filter with where so we want to use this item ID is going to be equal to the ID which is going to be provided so now let's create here the item ID okay now let's create here our function and we want to get the item and basically here we have to pass in the item id whenever we want to access this this is just going to be of type int and this is just going to return a flow and it's just going to return a single item so as you can see here we are just filtering our database by matching the IDS which is going to be provided here so for example whenever I click a single item here and we want to open it we have to pass in the ID and tell Rook database to filter this data when they match their IDs so this is just one way of creating our dial now let's create another dial for another item okay now let's create another interface and we're just going to call this store down and this is just going to be similar to the data which we have written there for the items but let's just call this at Dao and basically we want to provide the methods which are just similar to this one so we can just easily copy this and paste it inside here so instead of items here we want to insert the store and here instead of updating an item so we have to pass in a store and here for example on getting all items we can just easily change this to get all stores and here we want to select the stores table and it's just going to return here store okay and here we want to get for example a specific store we just easily call this get store basically here we can pass in the store ID and here we want to select from the store table and we want to change these variables here to be the store ID is going to be equal to the store ID which is provided here so as you can see when we want to access this you have to pass in these two columns here and for case the return type here is going to be store okay so these two dials are just similar so we're going to write here a shopping list now which is just much more complicated so now let's write it okay now let's create here our new interface and we can just call this list down it's just going to be the dial for our shopping list and we can just easily annotate this with ADD Dao okay now we can just easily create our methods so for example here the suspend function and we want to insert the shopping list so basically here we're going to pass in the shopping list as normal and here we want to annotate this with ADD inset and provide here the uncomfort strategy and we want to replace this so we can just call this on conflicted strategy and but replace and basically it's going to replace so this is just similar to those which we have written okay now let's create here our function to get the items with the stores and list so we're going to join between multiple tables so we can just create here a new function and we call this get items and basically this is just going to return us our stores okay so we have to write here add query and provide our query so because this query is going to be long so I'm going to using this string template here so that we do not have problems when we are writing and for visibility purposes okay now we want to call here our select as normal so we want to select everything from the items table okay so we are going to use here as keywords so that we can rename the table name so that we can easily refresh this when we are writing inside our query we can use these items as I and we want to provide the inner join keyword and this is going to tell hey we want to join between the items and this particular table so we want to again join between the items and the shopping list table and we can just rename this as s and now we want to provide the condition to join between these two tables so we can just provide on so the on keyword here is going to tell hey we want to provide the condition to join between these two tables and as you know inside the items table we saved the items and the shopping list ID so we can use here the for example the list ID and this list ID must be matching with the ID inside our shopping list so we can just use as dot list ID so basically here now we are going to compare between these two if they are equal then we can just return that item and also we want to provide another inner join and we want to join this together with another table so we can provide here inner joins and we want to join the store table and we can just rename this as St so that we can easily reference this inside our code and now we can use this we can provide their own keyword so that we want to filter this again so we can just use I dot store ID and this is just the following key of the ID which we have and then we want to match this with the stores ID so we can just use St but store ID so as you have seen here now we have performed our query so we want to select everything from the items table and we use this as to rename these item's name so that we can easily refresh this inside our code and we use this inner join to tell that we want to combine between the items and the shopping list table and as you can see here we use this on keyword in order to provide a condition to join between these two tables and for kcr we are using the list ID foreign key and also the list ID which is just going to be arising from the shopping list table and basically when these are going to be true then these items are going to be joined and also we perform another inner join again to store to join the store table and for this case we provide the condition that the store the items the foreign key that is stored inside the items table must match with the store ID and for this case we are going to return our item for now here we have written our query now we want to return all of these items so as you can see here we are joining between three tables and then this is going to return three entities the items the shopping list and also the stores so we don't have a single data class that is going to manage to hold all of this data so we have to create a separate data class that is going to hold this data and we can easily use it inside our UI when we want to display our data so for this case we can just jump below here and call our data class and we want to call this items and now we want to insert these two items so for example here we want to call this item and also here we want to pass in the shopping list and also we want to pass in the store okay so all of these items are just embedded and we have to tell the room that these items are going to be in embedded and the embedded item is just when we provide or we use a join query because we're joining between three entities and for this case we can use just an annotation here and call this at embedded okay so as you can see here we are just returning all of these items in one row so for this case we can just provide here our flow at least with items and store so whenever we use this type of join query then we can just use these items with this store list and retrieve it and use it inside our UI now let's provide another method that is going to help us to filter this for example according to the list so for example when we provide here an ID and we want to filter them according to certain categories for example the shopping list so you can just easily press Ctrl C and copy this and pass in here Ctrl V and paste it here and now we want to call this filtered we want to filter this by list ID and here basically we can just easily add another another condition here which is just by using a wire close so for example here where and then we want to check between the store and if this is just going to be equal to the list ID which we have and here basically we have to provide the ID which we want to filter with so we can just pass in here the list ID so basically here we're going to pass in the list ID so that we can easily filter our data according to this list ID so we can just pass in here the list ID so we have added here aware clause which is going to filter this according to the the stores according to the list ID and also we can just add another method which is just going to get us a single item with just the which which is filtered according to the items ID so now we can just copy here Ctrl C and paste it here now we want to call this we want to get the item and now it's not the items we're going to return a single item with a store and list filtered by the ID now we want to pass in here the item ID and basically instead of using here the street we can just use the item and pass in here the item id which is filtered with the item id which we have passed here so you're going to see this when we use inside our UI so here we are just filtering we want to get a single item so instead of a list we can just change this here and we want to return the items with store and list so here we want an item filtered by the item ID and here we want to filter this according to the list ID and for example here we have used this store so here we have to use the S which is just for shopping list here and not the St which is just for store we can just use this s ort list ID and instead of filtering this with using the store so we want to filter this according to this store ID which is just the ID which we are going to be providing here now we have finished to create here our methods and the dials we can easily now create our database class which is going to help us to connect between the database and provide us with the access to the dials so now let's create here a new class and we can easily call this topping shopping list database okay so this is must be an abstract class and must inherit from the room database so you can just easily call this room database and we have to annotate this with at database and now inside here we have to provide the entities so this is going to provide us with the connection to the database so we provide here the entities which we have and this is just a an array and here for example you have our first which is just shopping list so we provide all of the entities which we have created and the last one which is just the store okay so the first case we have finished now we have to provide the version so this version here is really important for example when we want to migrate our database to another version then we can easily bump up this number so if our case here is just the first version and then here we have the export schema and for case here we are just going to pass in this to be first so we're going to see these when we write the migrations so for now we are just going to leave this as false here okay so now we want to provide the access to the dials because this method is going to manage the connection and creating the database so we have to get the method so that we can easily access our database so for case here we can create an abstract function which is just for example the list down we want to be able to access our list down now let's first create here literal and this is just going to be of type list Dao and it's going to return our store now okay so we have said that we this database class is responsible in creating the connection to the database so we have to be able to create the database from this class so how can we do this and creating a database is just we have to manage the threads and also we have to get a single instant throughout our application so and an abstract class we cannot instantiate this class here because this is just an abstract class so for this case we can easily create a companion object because this companion object here is going to help us to create the instance of this class without instantiating this class so for this case here for example we want now to create our instance and the first case here because this is going to be accessed in different threads we have to manage the threads and basically we can use add volatile and this volatile here is going to tell hey you have to manage this in a thread safe Manner and we're going to do this now let's create here an instance where and call this instance and basically this instance is going to return a shopping list database and basically this is going to be nullable for the first time because this whenever we instantiate for the first time we want to make this to be null so that we can easily instantiate now let's create a method that is going to get the database so let's create here a fun and we want to call this get database and provide here a context which is going to be used to instantiate the database this is going to be of type context and now this is going to return the shopping list database okay so we're going to return the instance but this instance is going to be nullable for the first time but we have to use this Elvis operator here so if this is going to be null then we have to create a new database and for this case we can just use a synchronized and this basically is going to look only a single thread is going to be able to do this so for example if we have multiple threads that are running in parallel and call this gate database then whenever we provide this log here it's going to lock this and only one instance is going to be able to access this and for that case now let's create our new instance so we can just call this instance with the small letters and now we can use our room in order to create our database and now we can call database Builder and now provide the class name which is just the shopping list database and here basically we can just provide the name but for example here we can just call this shopping database and basically here we can just call Dot build and this is just going to be building this and now we want to instantiate this instance here to a new variable because we have already created an instance here so we can just call this instance because to this instance and basically here we have created our instance and we can just call return instance okay so the second time we call this get database here because this instance is no longer going to be null then this instance which we have created here for the first time is going to be returned so we will not call this code because this is not going to be nullable so this is how we create the the database in the thread safe Manner and we have only a single instance throughout our application until when it's going to be killed and create a new database when we re-launch our application okay so now we have finished to create here our database we can just easily call this build here or make project so that we can see if we have any errors and fix them now let's just press this and make the room database to generate those implementation of everything which we have written here and the error is just filled has a non-unique column name as you can see here we have a column name that is called list ID FK throughout our Dows so let's just come here inside our models as you can see here we have this list ID foreign key and also this is just called the list ID foreign key so we can just easily change this list ID foreign key so we can just create here shift F6 so that we can just change this and we can just call this list ID so that we can just differentiate them now we can just easily refactor this and it's going to refactor everything so here instead of list a different key we're just going to pass in as a list ID okay now let's rebuild again see if we have any problem okay so this is just the great thing about root database because it provides compile time verification so as you can see here now room is complaining again that it cannot figure out how to save this field into database so you can see here it's providing us with the suggestion you can consider adding a type converter for it so we're going to see this in the next video how to add type converters and save custom types which are not supported inside our database so as you can see here we are saving a data type that is called that and inside sqlite you cannot save a type that is called that here so for this case we have to provide type converters so we are going to do this in the next video so for this video let's leave it here so if you find any value out of this video please don't forget to provide a like And subscribe for more videos so see you in the next video bye bye for now
Info
Channel: HoodLab
Views: 4,807
Rating: undefined out of 5
Keywords: shoppinglistapp, jetpackcompose, roomdatabase, datalayer, androidtutorial, androiddevelopment, appdevelopment, mobileappdevelopment, roomlibrary, crudoperations, databasemanagement, jetpackcomposetutorial, appcodingseries, appcodingtutorials
Id: D7PW4P3FmnU
Channel Id: undefined
Length: 36min 4sec (2164 seconds)
Published: Sat Jan 28 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.