The FULL Beginner Guide for Room in Android | Local Database Tutorial for Android

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey guys and welcome back to a new video in this video I will give you a full guide on implementing a local database in Android using the room library and if you've been following my channel for quite a while now then you will know that I use room in pretty much all of my projects where I use a local database and I still notice that I don't have a guide that is fully dedicated to to this Library which is so prominent if you're an inner developer in this video I will give you as a beginner for the room Library a full guide on how you can build such a contact list app it's a very simple app but it teaches you the basics of the roon library I'll suggest a beginner guide we will save context for the first and the last name and the phone number and we will then be able to order based on these three values so we can order by first name which is currently selected we can order by a last name you can see it switches and we can order by phone number which is then yeah in this case does not change anything and all this ordering in this case is not done manually with a simple sorted by function no we actually order this directly with an SQL query so you can also learn how to do that with room and of course you will also be able to add a contact by clicking on this Floating Action button then a little dialog will show up we can enter first name something like James for example James Smith and we enter some kind of phone number I have no idea if that exists I hope not we we click add contact and there it is it is added in real time so you can also learn how you can directly observe these changes in your database and then you will also see different ways of sorting depending on what we select here and as you probably also noticed we do have these trash cans here and if we click them we obviously delete an existing contact in our contact list app if we then decide to close this app and relaunch it then well it's a local database so we still get our entries which is exactly what we want so that is what you will learn let's dive right into it into an empty and receive your project and the first thing you need to make sure to be able to follow through this video is you need to add the dependencies in your build a Gradle app file to be able to use room so you can see we'll find the room version I think as for now that is the latest version that is supported and then we need this line for the room KTX import with that corresponding version and we need this capped import which stands for kotlin annotation processing for for the room Library we use annotations a lot to define or to Mark different classes for example as the database table or as a database class and room will then process these annotations for us so we really only need to define the minimum amount of code to be able to use this cartoon annotation processing you also need to make sure to scroll up and add this ID carton cap otherwise Gradle won't find it after that make sure to synchronize that and we can jump right into coding so when it comes to creating a database or working with databases we usually need three different things especially when we work with a room on the one hand we just need a database so something that holds one or multiple tables one table could be something like in this case a contact so the table will contain multiple rows as many as as you can as you have storage on your phone basically and every single row will correspond to one single contact in this case and then in addition we will have multiple columns because it's in the under table each column will be one field of one row so one field in our case of a contact one field would be for example the first name one field would be the last name one field would be our phone number and we can actually also inspect that directly in inner Studio how our room database looks like so I still have my app open here and if we now go to app inspection on the bottom here and select a process in this case my emulator and we choose this room guide then wait a little moment and it will load this database inspector you can see here is my contact table if we double click on that here we see our actual database so we have a bunch of columns in this case an ID which is a unique identifier for a specific contact in this case we have a first name last name and phone number and every single row will now correspond to one instance of such a contact so this whole thing here would be the database then the database consists of multiple tables and okay it's just a single table to keep it simple but you could also connect different tables for example if every single contact of your app would be able to have one or many addresses so for example a home address and a work address then we couldn't really easily model this with a single table since you could have theoretically an infinite number of addresses in that case we would make it a different table to have a separate address table in which we can store addresses and then we can link our two tables so the contact table and an address table to say hey each contact has many addresses so that will be the purpose of having a table in a database so that is the second thing we actually have for databases that we have a whole database that hosts multiple tables and each table which hosts multiple fields for a specific type of object in this case a contact and we need a third thing especially in it for room which is the so-called Dao that stands for data access object and it's basically an interface in kotlin where we Define how we want to be able to interact with our database so that is the place where we Define hey we want to be able to add contacts we want to be able to to get contacts ordered by first name we want to get context ordered by last name all these kinds of queries and functions we want to use with our database we will Define the so-called Dao object and with these three things we will implement this video we have a fully functional database in Android so let's actually jump into coding I'm sure you're already excited and but I still think it's important to understand the theory before jumping into practice first so the first thing is we want to start creating our table in our root package we will create a new class called Contact and that will be a data class in which we just Define the fields each contact should have so on the one hand of course the first name which is a string the last name which is a string and the phone number which we also store at the string and as I also already said each single table in a database needs to have a so-called primary key a unique identifier we we can use to say okay we want to find the contact with the idea one and we we want to be sure that there is exactly one single contact with that given ID and to Define that we want to say valid and we can choose a simple integer ID here you can also choose different types also string IDs you just need to make sure that they are unique for integer IDs we have the advantage that room can automatically generate them so they it will just increment them when we insert more contacts but we need to tell room that this is our primary key because right now it's just a plain data class and room doesn't know that so we need to add an annotation primary key and that will tell room hey please use this ID as our primary key in case you don't want room to Auto generate this primary key you can also set auto generate to false here I'm noticing that it is already set to false by default so let's set it to true instead to make sure that room will Auto generate this and I still think we need to actually assign a default value here for which we can simply choose now if we add a contact and we leave this at now then room will yeah just generate a random or a unique ID for this contact and I think we should also be able to make it non-nullable and set it to zero initially let's just try that um since it's a default parameter I'll move it to the end and something we need is we need to annotate this with entity an entity is basically the same as a table in room and that will already be fine we have some options we could specify here we could change the table name which defaults to the class name so we don't need to change that and we could do a lot more we could Define foreign Keys primary keys if we would have multiple but that is more advanced database stuff we don't want to deal with that here then the next step is to go to our root package again and now I want to create our dial or data access object for this table so I want to have a contact Dao which is an interface and again to tell room that this is our data access object or one of these you can actually have multiple Towers I'm going to annotate this simply with Dao and then here now go all the functions we want what we need to be able to modify our contacts table on the one hand that is a function to save a contact or to Simply insert a contact to phrase it in database language here we then need to pass the type of entity we want to insert which is simply a contact and then we actually don't need to write the implementation of this since that is what The annotation processor will do for us and then to tell room that this is our insertion function we can annotate this with either insert which will simply insert a new value or something that is quite new to room is the Absurd annotation so absurd is a mix of updating and inserting so if there is already a contact with the ID of the contact we passed here in the database then it will instead update the existing one if we use insert instead then it will simply insert a new one and it will complain if there is already in the contact in the database with that given ID however we can also specify a so-called on conflict strategy here um so if there is a conflict if we insert a contact with an ID that exists in our database already then we can say okay what should it do the default is a board so it will simply probably throw an exception I'm not sure here but you can also set it to ignore to simply don't do anything you can set it to replace which is then the equivalent to upserting but since we have this new annotation in room let's just use this to Absolute a new contact and we can also name the function like that absurd contact so it inserts if it doesn't exist and if it exists it will replace it then the next easy function we can Implement here is a function to delete a contact which you can pass here and that is also super easy with room we just need to annotate it with at delete and one thing about these two types of functions where we simply do something and we don't really get some type of data here so we don't really um query for context we can make both these functions suspend functions and kotlin so they will actually um run in a carotene and yeah just block it until that database operation finished so I'd always use that in case you stick to using core routines for asynchronous programming or yeah just flows now coming to defining our queries because we want to have three different ways of querying contacts from this table on the one hand a query that gives us our contacts ordered by first name ordered by last name and ordered by phone number so we need three more functions and that will be a plane function and get contacts ordered by first name is the first one and what will this now return well with room we have different options here we could simply return a list of type contact so it will simply give us all the contacts we have in our database ordered by First Chain but the cool thing about room is that it actually is able to give us observables so things you can observe and things that notify you as soon as there is a change in the table and that is the true power about room so what we can do here is we can simply say we want to get a flow of type list of contact and the flow is such a data type or data structure and that will notify us about changes Whenever there is a certain change in this table so whenever we insert a new contact for example then this flow that we already got will emit a new list of contacts that includes the newly added contact and the same also works with a live data I'm not sure if I can use that here yes um I don't need the the dependency um so if you're using live data you can also get that here and I think there might also be something for RX Java but that is a little bit more old school I like using flows and one more thing we need to do here is to define the query for room because right now just from this function name room doesn't know how it should get this first these context order by first name so we're going to add a query here query annotation and in here we can just Define our SQL query how we want to get these contacts so we want to select everything from our contact table and we order these by the first name field and the order should be ascending which is the default but let's specify it still and that is everything we need to do to get this function because room will yeah just make sure that the implementation of this will be generated behind the scenes for us so we don't need to write that on our own we now want to copy this paste it two more times once for the last name and once for the phone number and we just need to change this to last name and this to phone number like this and then we have a fully functional dial and the last step to have a database a functional database is to Define that actual database so we now just need something where we tell room how it should connect all these pieces we now implemented so we need to tell room hey these are all of our tables we have in our database these are all of our dials and we need to create a new class for that so no root package I'm going to create a new file called Contact database in this case select class here and this is actually an abstract class which needs to inherit from room database like this in this abstract class we can now Define our abstract vowels for all of our dowels in our case we only have one so we say Dao of type contact out and since it's abstract we don't need to implement it since again room will do this for us but something we need to tell room is that this is our database class and we do this by adding an annotation again add database and here we on the 192 specify our entities so our different tables as a list and since we only have one entity which is our contact entity we need to specify that here with contact double colon class and we need to specify a version the version is needed to tell room when there is a certain update to our database how it should actually migrate the old data to the new data we don't need to deal with that here I have a separate video about migrations so if you reach that point um feel free to check that out but we are fine right here and that is already the database logic that you need to be able to just use your database with the given functions here of course we still need to build our UI which is the larger part of this video because I think it still helps to to implement this once with a fully functional app that does something but we already finished implementing our database we now just need to call the corresponding functions when we want to do that so when we click the add button for example to upset a new contact we want to first of all go to our package and I want to create something like a contact event that will be a sealed interface case and to be exact this class will basically just contain different events an event would be something basically a user action so something the user does on our screen for example clicking on The Floating Action button for example clicking on deleting uncortex or clicking on the trash can so basically any type of user action that is possible on our contact screen will be represented by one event here that's just a very handy way to handle this user interactions in our view model later on so on the one hand when I have an object to save a contact so that will simply save the contact where we use the data the user entered in the text fields and that will be a contact event it doesn't need any parameters since we already know everything we need to know we then want to have a data class when the um to set the first name so when the first name changes we pass this here so when the user types something in the first name field contact event duplicate that two more times to have the same for the last name last name and of course for setting a phone number as well I like this whoops we don't want to have an object to show our dialog and we don't have an object to hide our dialog so the dialog is used to add a new contact we also want to have a data class to sort contacts which will will pass a sort type and that is an Edom class we need to create so let's do that here in our root package new class called sort type select enumclass and this will basically just contain the different types um or the different fields we can sort based on on the one hand we have a first name we have a last name and we have the phone number just like that that's already it we can then go back here past the sort type and Implement contact even again and finally you want to have a daily class to delete a contact when we click on the trash can where we pass the contact we clicked on like this next up we want to create a little State class so just a class that combines our screen state so that includes our contacts list that is currently displayed that includes the currently selected radio button for the Sorting that includes whether we want to show or hide the dialog and things like that so in our package new class called contact State make that a data class and here we put in all these fields on the one hand our contact list so a list of contacts which is yeah the default um is an empty list we want to have the first name so on the text of the first name text field and the dialog will have the same for the last name for the phone number and we want to have a Val is adding contact so if the user is currently adding a new contact to show the dialog which is also default um which defaults to false and finally once you have the current sort type so yeah that will be used to decide with radio button is switched on the default sort type is first name first name like this and now since we have our state we have our events we can now Implement our view model in which we will map all of our states so new class contact View model whoops view model select class make that inherit from viewmodel and here we simply want to pass our Dao in the Constructor so simply contact dial and this view model will simply host our state so that will be a private valve underscore state which is a mutable State flow I like to use State flow here feel free to also use compose data so where we will just have an uh empty contact State we also need a private Val for our sort type which we selected and I know I passed this in the context set but you will you will learn in the next few minutes why I make that a separate field which is also a separate mutable State flow with the sort type first name by default and we want to have another private valve for our contacts so the currently displayed contacts which is a mutable State flow oh no this is actually an immutable State flow let's leave that for now and we'll Implement that in a moment after we implemented our on event function so as soon as there is some kind of user interaction if the user presses a button type something in a text pillar so we will trigger this function with the corresponding event for example showing the dialog if we tap on the floating action button to change the phone number if the user types something there and things like that so in here we'll just have a big one expression depending on what the event is we can press Alt Enter to add the remaining branches and now for each single case we can handle that very easily here in the view model when we want to delete a contact what do we want to do we want to call our Dao and say delete contact and the content we delete is passed to our event you'll notice we get an error here because we need to execute that in a quarantine since that is the suspend function so what you can do is we can launch a codeine in viewmodel scope launch put that in here and we won't have any errors anymore then if we want to hide our contact dialog you want to say underscore state that update to update that state and we only want to update our dialog so is adding is adding contact is false so we're not adding the contact anymore if you want to hide it and yeah that will simply leave the remaining Fields unchanged it will just change the single field we modify here and then for saving a contact that is probably the most complex function or the most complex case here for our when expression here we first of all want to get a reference to the first name of our state which is state that value no we don't have that yet let's choose um no let's leave that empty for now and Implement that at the end let's implement the easier functions for now set first name is easy State update hit copy and the first name text is simply event.firstname we can then copy this and do the same for selling the last name and setting the phone number so here we pass last name here with pounds last name and here we say our phone number is event.phone number when we show a dialog we can actually also paste this here we can say is adding contact in this case is true if you want to show the dialogue of course and I want to sort the contacts we want to say State um actually not stated we just want to say underscore short type dot value is equal to event that's so type so we just update our sort type mutable State flow so now only our safe contact case is left and we need to implement our real state so right now that's only the mutable state but we we only want to expose immutable states to our UI since the UI shouldn't really be able to directly manipulate state of a review model so since for our contact dial for each single um sort type we have your first name and last name and phone number we return a different flow from our database it's quite tricky to make that work and combine that to a single state in our contact viewmodel that is now a bit more advanced flow stuff and I do have a playlist about flow operators and stuff like that so feel free to watch that in case that is new you I will of course do my best to explain this here what I do so what we will have is we will have a private Val underscore contacts for our contacts state which just always holds the current contacts that considers our sort type so we will say we have our sort type and we then say that flat map latest where we get access to this sort type and depending on what that sort type is we will have one expression I'll enter to add these remaining branches if it is this first name sort type we map this to down get context ordered by first name if it's last name down ordered by last name or a Dao dot ordered by phone number and the reason we do this is flatmap latest if we check the documentation here it will basically take a flow which is our sort type and whenever that flow changes so whenever of our sort type changes whenever we tap a new radio button we transform that emission so the new source type to a new flow and that new flow is in this case one of these flows that comes from our database so with that we basically achieve some sort of reactivity that as soon as our sort type changes we will automatically also change the source where we get these contacts from I hope that makes sense we still need to say um start state in to save that in the state flow to make it state so to to Cache it in this flow and we want to state in viewmodel scope we say sharing started while subscribed so this piece of code is only executed if there is an active subscriber to the state flow and we then say the default value is simply an empty list of contacts and then we don't have any issues anymore we get a warning since that's a bit experimental I think we can hit Alt Enter to add this annotation to our review model and then the warning will go away now this oops um is a state flow of of lists of contacts which always holds the context with the currently used sort type so as soon as we now change the short type here this will automatically trigger a change for this context list and it will automatically map this the sort type to the correct order and finally the list of contacts I hope that makes sense we can now go ahead and do something a little bit similar with our state so that will be the public version of our state that we're exposed to our UI that all the UI will observe and that is equal to combine to combine multiple flows into one on the one we want to combine our state we're not combine our sort type and our contacts I'll explain that in a moment um let's say oops state sort type and contacts and we then say state.copy context is contacts short type is search type and we again say that state in pass five seconds here don't worry I will explain all that and the default value is contact state so what the heck happens here with combine as I said we can combine these three flows into just one flow so as soon as any of these State flows emits a new value this piece of code will be executed so if there's a change in sort type we um we update the sort type of our contact State correspondingly here if there is a change of our context so if the sort type changes for example which changes the context then we will also update the contacts in our in our screen State as well and of course if there is a change in our state this will also be executed and the reason we add these five seconds here and not here is that this is a flow that is directly consumed or observed in the UI and this just to make sure that there is a certain bug we can't have when this flow would emit a value when the activity is directly in the undestroited state where it actually shouldn't get value so it's a quite complex bug but this is something we we can use to make sure we don't have that back I don't want to dive deep into this here um I covered that in another video and now that we have our final stage we can also Implement our safe contact function before we jump to implementing our actual UI to display all that here we first of all want to get the first name of our state so the text field value we're going to get the last name like this we want to get the phone number and then we want to check if any of these are empty oops phone number of course I want to check if any of these are empty so if the first name is blank or the last name is blank or the phone number is blank then we just want to return out of here and not insert anything because then we don't have any data to insert then I want to make sure that we create our contact we want to now insert into our database which is a contact first name is first name last name is last name and the phone number is the phone number and the ID will be automatically generated and then we can say we launched a 13 in view model scope to insert that and we say down upsert contact and we pass the contact we want to insert after that we want to say underscore State update and we update it on the one hand with is adding contact set that to false to Simply hide the dialog after we added a contact and then we reset our text fields to empty strings and phone number so now that we have our review model we can finally start building our UI and then we can try this out so in our root package let's have a contact screen select file make that a composable contact screen and this will take two parameters on one hand over State and on the other hand an on event Lambda which we trigger when we do a certain thing on that screen which corresponds to a contact event like this so what will be on this context screen if we take a look here we will have a column in the end just a lazy column for everything we will have our row of radio buttons first and then our that will be just be a lazy column for the context where we have a contact item we have a row and a column here for these two names and the phone number and then we'll have our Floating Action button so we put everything in a scaffold that is the plan year so we as I said the outer layout will be a scaffold which makes it easy to add a floating action button in here as a parameter we can then we get the padding values here and we can say we use a lazy column and the padding values of this lady column will just be what's content padding content padding will be padding like this we then also want to say modifier is modifier fill Max size and import modifier Alt Enter and we want to make sure that the vertical Arrangement is arrangement dot Space by to make it so that there is always 16 DP of space between each list item you can then open this block of code here um let's start to implement this Floating Action button up here so we have a floating action button when we click this we trigger our own event Lambda with our contact event dot show dialog since if we click on The Floating Action button to show our dialog to add a new contact and the content of this Floating Action button will be an icon which will correspond to icons default dot add and the con description will be at contact like this put that on separate lines for some reason I don't get the help of function for that it doesn't matter let's format it like that and then jump to our lazy column in here we first of all want to have a normal item which just holds one item which will be the row for our radio buttons so this row will have a modifier to fill the whole width of our screen and it will also have a horizontal scroll here we say remember scroll state so that will basically make sure that we can yeah scroll horizontally here for our radio buttons to also be able to yeah pick the phone number the vertical alignment of this row should be Center so we just Center all these radio buttons vertically and in here for the row content we just want to take our sort type then values to Loop over all of our values all of our different sort types and get a reference to these and for each sort type we now want to have another row so that will now be a row that holds this radio button and the text next to it so in here our modifier will be modifier dots clickable because if we click on such a row that holds a radio button and a text then we want to call and we want to call on event with a contact event dot sort contacts with our sort type we clicked on we also want to make sure that we Center all these items vertically in this row um and we can also import that pressing Alt Enter and in here we'll have a radio button when is that radio button selected well if our state that sort type is equal to the current sort type We're looping over um in on click when we click on this radio button we can also simply paste this event here so that we sort our contacts based on the clicked on sort type and after that radio button we will have our text which will simply say yeah let's just say store type dot name that is something very simple so we just display the exact name of our enum enumclass and that is it for our job Row the next thing would be another item in our lazy column which will be an items block to display multiple items make sure to import this one here with items a list of type t and Pass State the context so for yeah we will now display an item for all of our contacts and get a reference to each one here so each contact is in the end just a row where we have a column first and then an icon button last so let's just make that a row modifier is modifier fill Max with and in here as I said we'll have a column for our first name last name and then below that our phone number here we say modifier modifier weight one F that will cause that this row will occupy all the space until the the other items so in this case just the icon button and in here we're going to have a text the text in this case is our contact DOT first name space contact Dot and last name oops look at this and the font size is 20 SP Alt Enter to import that and below that first name last name text we're going to have another text for the phone number so contact that phone number like this and yeah I set the font size to 12 SP a little bit smaller and then finally after this column inside of our row we're going to have an icon button and when we click that one to delete the content we clicked on so here we say on event contact event dot delete contact and the contact we clicked on is but just our contact you can then say we have an icon for that icons default delete and the description of that is delete contact like this oops cool that is it for our contact screen the last thing that is missing is our dialog when we click on our Floating Action button here so in our package we can create a new file called add contact dialog select file and make that a composable add contact dialog which will take our contact state it will take on event function again which is actually a Lambda of Tab contact event to unit and a modifier like this so in here you want to have an alert dialog that's actually quite simple to implement that um and in here we have on dismiss request which is called when we tap outside of the yellow dialog or dismiss it in some other way for example by pressing the back button we are going to need a title which is simply a text composable with um add contact or so we're going to need some text the text can be anything here so I will just choose a column of text fields in this case here we can say the vertical arrangement is arrangement spaced by ADP up to make it so that there is ATP of space between each single text field and in here we can then spam our text Fields basically the first value is State um first name so first name text field value and one that changes we say on event set first name with our new value we can also give it a label label or placeholder is it called let's use a placeholder and which is basically just a hint what we need to enter and this would be first name and then here we can copy and paste this two more times the second one is for the last name set last name and the placeholder is last name and the last one phone number set phone number and phone number and then below our text one more thing we need is buttons or just one single button in our case here I'm going to use a box where we say we fill the whole width of our dialog and then inside of that box we're going to use a button when we click that button we say we color on event contact event dot safe contact since if we click on our add contact button then we just want to save that of course the text is Save contact or just save and let's also make sure we align this button to the end of our box content alignment is Center end like this and that we assign the modify yet nope we can also do this here the modifier is modifier on this Miss requests here we are going to need to call on event with contact event dot height dialog in this case and that is it now we only need to take this add contact dialog to our contact screen right here and check if we actually want to display that by checking if state is adding contact and if so we call our add contact dialog with our state and our on event function and yeah that is it for our UI of course now need to call this contact screen in our main activity so let's switch to that say we have our contact screen and in here we need a state and we need our own event landlord for that we need our viewmodel and for viewmodel we need our database so let's see how we can now initialize our room database and first of all normally I would totally use some form of dependency injection setup to have a global place where you manage your dependencies something like a dagger module or so but I think this would maybe overwhelm some of you if you haven't worked with dagger yet in Android or dependency injection in general so I will just initialize our database in here about please keep in mind that this is not the the optimal way of doing that in case you want to learn dependency injection then please just look on my channel and search for dagger Hilt crash course and you will uh yeah just learn why there are certain better approach so we're going to have a private DB here which I'm going to initialize with the lazy so buy lazy and in here we will say room so we call room again Dart database Builder we need to pass our context where we pass the application context we need to pass the class of our database we want to initialize here which is our contact database double colon class dot Java and the name of our database file so where we save this is just contacts.db and then after that we can call that build to finally build our database then the next thing here is our viewmodel we can say private valve viewmodel buy view models that is how we initialize the view model in an activity and we say that is our contact view model and since RV model does take a parameter which is our dial we need to provide a factory um that is exactly necessary if you if your viewmodel has some parameters if you use something like dagger hild you don't need to create your own Factory because dagger does that for you but we need to do that here for the sake of Simplicity and we can just say object colon viewmodel provider.factory and override the create function here to return our viewmodel instance the way we want so we want to return a contact view model where we pass our down we get that from our DB so we simply DB you can see that is now a contact database and we call that Dao on that and now we can simply say as T so we cast that as our return value here that is just how we create a view model with parameters looks quite complex but is really only about this line of code here and then we can finally get our state in compose so Val state is equal to actually buy view model State collect our state to just get on that state and observe that then we can pass here State and on event will be viewmodel double colon on event we probably missed some padding on our screen so we could also quickly add that to our contact screen by adding some padding to our outer scaffold so modifier is modifier padding 16dp and that should be it I would say I would say we just try this out run this on my emulator and hope for the best so this is still my olab of course Gradle will probably take a moment and then I'll see you back okay so this looks a bit weird here because of the padding in the scaffold because the scaffold has a different background than our root view let's care about that later our radio buttons are displaying um we can switch these that is working fine and if we now want to add a contact that is the interesting part um the dialog does not look very very beautiful but it is hopefully a functional one so first of all the first name last name phone number clicking save and there it is there is our contact in our database because otherwise it would not even display let's first of all check if the Sorting works so we add a new contact first and last entering some from a phone number now it is ordered by first name which is correct because F comes before P um last name should now put this one as the last which is correct and the phone number should put this one here as the first one which is also correct so that is working perfectly fine if we rotate our device this is hopefully working fine yes it is oops um that was messed up um let me quickly turn this back yes um we wrote it back that is working fine and if we now delete the contact like the first last one then that is also working fine if we relaunch our app we hopefully still see our Philip contact which we do so we now have a fully functional database in Android to fix this little padding issue we can remove the padding here of our scaffold and move it one step below to our lazy column let's actually just ignore this padding here make it unused and pass padding values of 16 DP here this should hopefully fix this if we relaunch this then yeah now that is looking perfectly fine cool now we have a fully working contact list app not a very beautiful one but a functional one and I would really encourage you to extend this app to keep on learning about room so what you could do is you could Implement behavior that if you click on a contact you actually get to a detail screen which displays details about that contact maybe even more details than in this list you could also add things like an address you could add things like an email address or so um so you really have a real contact list app because just watching a video in the and is great but it does not really teach you how to do it in practice you can only learn that by actually doing it in practice so I really encourage you to do that at home and if you feel like you need help with more advanced Android projects then definitely check my Android premium courses down below first link in this video's description uh where I have a bunch of courses which will make you an industry ready and a developer so thanks for watching and I'll see you back in the next video have an amazing rest of your week bye bye foreign
Info
Channel: Philipp Lackner
Views: 33,165
Rating: undefined out of 5
Keywords:
Id: bOd3wO0uFr8
Channel Id: undefined
Length: 47min 18sec (2838 seconds)
Published: Wed Mar 15 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.