Full Room Database Tutorial - Build Notes App With Room DB

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi what's going on everyone welcome back to a new amazing video which is a room database full tutorial video so in this video we'll be implementing room database uh so basically we'll be building this app which is a simple noes app and we'll be using note I mean room database to store these notes uh in the user device so basically this is how the app is going to look like we can of course uh Delete notes we can sort them based on the date they were added or the uh the first character they start with uh so let's add a new note for example here let's call it new we can give it a description like test or something and then click save so here's our new notes we can as I said sort them so right now they are sorted alphabetically uh a and so on and then if I change the sourcing now they are sort sorted in the date they were added on this is the first first one I added and this is the last one and I can always delete a note and then Resort them the one I want and if I close the app and they launch it again I'll find that my notes are still there and to know how room database looks like or works we can just go to the app inspection here and then wait a little bit so this is our database it's very simple it's just a table that has the the most important thing which is the ID and room actually room database generates the IDS for us so they are autogenerated we don't generate them we don't generate them we just uh of course uh give our note a title by ourselves and the description and then the date they were added we Pro we do that programmatically and then room database adds the ID uh automatically so it's very simple this is how it looks like this is you could call this note as a data class that has a bunch of attributes which are uh the title the description and the date added and then the ID which is the primary key as you can see here a little key icon which is autogenerated so let's get started and see how we can build this app using room database so the first thing is that we want to add the libraries we want in our build. grader file so let's go to our build. grader first of all we need the C annotation thing which which cap stands for cutlan annotation process that we just need because zom data basic just a bunch of annotations as I said everything is done behind the scenes we don't do much things uh we just add this plugin here and then scroll down here we want this room Library basically this is latest version uh of course there is another one uh instead of C that is key SP but it generates some errors so I'm just going with C for now so we add these two libraries here with these two dependencies and then the navigation one because I navigate between two screens which are the home screen and the uh add new Note screen and then the extended icons Library just for uh the icons like I love uh to have many icons in my apps so I can use them or you can you can if you don't want this you can just avoid it just add these dependencies and then sign the project and you're good to go so the first thing is that I want to add some packages I need in here I will add two packages the first one is the is uh the data package and then the presentation package basically the data one will hold or we will include everything that has to do with data uh from the data object uh the data like uh the note Dow you I will explain this later and the note database itself and then the other one is the uh presentation package which which will have everything has to do with the UI from like the screens The View model the state and the events like everything will be there so first of all let's create the data package so data oops data like this and then the presentation one and click enter in the data package let's first create our note so new cink class or file I'm just going to call it a note and it's a data class of course so the first thing we want to annotate this data class with entity because as I said uh room database is a bunch of annotations so I just add entity like this and now entity is just like a thing that we can add into our table so room knows what to add basically we add entity and then we add the attributes we want here in our data class so V title which is of type string and then uh the description so V description of course as well of type string and then and the last one is V date added which will be a long and then the last thing is the primary key or the ID so I just write VAR ID which is of type int and by default let's make it a zero so to tell room that this is our our primary our primary key we just annotate with that so add primary key like this and then we set it to be autogenerated so Auto generated and set that to true I may have made a Tapo here description and the typo is gone so this is it as I said the we annotate the data class with entity to tell that this is our entity this is what we will be adding in each row in our table and then we annotate ID with primary key autogen at through to tell room that this is the primary key this is what separates each row from the other one uh and then we add this autogenerated TR to make it auto to make room generated for us and then let's move on and create the note Dow a note Dow is just uh we could say it is a note data access object and this Dow will be an interface that will make us perform uh database operations like inserting deleting and uh updating and all these uh database operations so let's create it so basically we'll go to the data package new uh cot link classin file and we'll call it note Dow like this and it is an interface and then as always room is just a bunch of annotations so we annotate this with Dow like this to tell room that this is our data access object and then we write the functions that we need to perform the room database operations the first thing is the uh insert a new uh note or a new object into our database we we say fun uh insert uh insert noes for example and then we'll pass our notes note not of type note we've created and then we annotate this with insert so add insert like this and then we just add the suspend uh keyword to make our function a synchron so suspend like this and we'll do the same for deleting so just copy this one that we already created and then create the other one for deleting so we call it delete and then here we just call it delete again like this and then basically before uh I move on right here you just format this there is actually a new one which is called the appert and this app uh not update upsert this one upsert stands for inserting update so basically this upsert uh if if we if we need to add a new note then it inserts and if we need just to update an existing one it updates it so because otherwise we'll have to create two functions one for inserting and one for updating but in the newer version of room there is upsert that does the two things with one just one function so we just we can just use upsert and then I can also change this one into upsert like this and so this is the uh inserting and updating function and then this one is for deleting so now let's create the ones that actually make us get uh the notes so the first one is uh to get the notes sorted or uh ordered by the date they were added so fun get notes ordered by dates added like this and this one will return a flow so like this it will return a flow that is a list of notes so list of notes like this and then I'm going to annotate this with a query so annotate query like this and the query to get to get notes or to get objects from the database is Select like this from oops from like from noes which is the note database I'm going to create it I didn't create it yet ordered by date added by date added so here I seem to uh import the wrong flow so let's reimport it import the this one the cortines one so this is uh to get the notes ordered by the date they were added and then the last one to get them ordered by the title so just come right here and then change this to title and ascending we can just write AC ASC and then we call it ordered by title so title and yes so this is it our for our note Dow that makes us perform all these uh room database operations in very very few lines like you can insert and upsert in one line and then get new ones or delete and get new notes in very few lines unlike the the uh SQL light basically room database is just like it does this exact same thing as SQL light but behind the scenes so we don't have to write all that Bott plate code because room does that for us and then last thing is we are going to create our database and it is very simple just come to our package and then create a new cink classing file we call it notes [Music] database like this and again we annotate this with database so like annotate it with database and then open uh two brackets like this and then we tell it what is the entity so entities is uh our note class so this is our entity and then the version so the version of the uh database basically when you change like something in your uh in your entity or you change like how you do the operations or something you can you can then change the version but for now just going to live it at one so we tell the the database that note which is this one is our entity and then uh the version is this one and the database itself is going to be an abstract class not a normal class so abstract class uh node database that implements room database room database like this and it has a Constructor and then inside here we're just going to create uh our or uh Dow variable so abstract Val Dow of type uh note Dow like this and this is it for our database so basically we just created our database and we are actually done with this one now let's create the UI but first let's create the view model uh so notes view model that's what I'm going to name it notes view model and so this is our view model that is going of course implement the view model this one and it has a Constructor and then in our notes view model Constructor we're going to pass uh our note D so private V I'm just going to call it Dow and it is note Dow so this is it for now for our view model we'll write the order code uh later but let's first create uh the events that the user can make uh in our UI or the actions like the events or the actions that a user can make so new cot link class in file and this one is going to be a sealed class and it's called notes events open the brackets the first thing is that the user can sort the notes so object sort notes that is of type notes event or basically I think it should be called event not events I think that's a better name because each event is just one event not a bunch of events and this one needs to be a sealed interface not a seal class uh the second thing a user can make is to delete a note so this will be a data class delete note that is going to take the note that we want to delete as a parameter so V note of type note and it's it's also a notes event like this let's import notes like that and then last thing the user can do is to save a note so as well I data class save note and uh the first thing we want is the title of the note so V title that is a string and then the description description this is also a string and that's it this is also a note event and this is it for the events that the user can make let's then move on to create the note state so the state of our screen so just call it note State and this one needs to be a data class and basically we need three three things in our notes State the first thing is this list of the notes V notes so list of the notes like the notes that we are going to display in our home screen so notes that is of type list note so list of notes and at first it is an empty list like this import notes and then the title Val title that is a mutable State type string and it is a mutable State empty string we need a little comma here and then the last one is the description and it's going to be just like title but it is the description like that so this is it for our state uh data class now let's go back to our view model so this is going to be our most complex class here in the app The View model because this is where we're going to try get in the uh notes removing them and this will be responding to uh we be receiving all the user actions and then perform the appropriate operation so the first thing I want to create is whether our a variable that tells us whether our uh notes are sorted by the DAT were added or by the title so private V is sorted by date added that is a mutable State flow and we initialize it with true because we want our notes oops true because we want our notes to be first uh ordered by the date they were added not by the title until the user changes that and then let's now create our own event function so fun on event that is going to take an uh event note event and then we just write when when so to to to know what event or what action the user did when event and then the Android Studio will add the remaining branches for us so we want we want to know when the user deleted a note and then when they save the new note and of course when they try to change the Sorting so let's start with the latting which is very simple so we just call uh use in our Dow we just call the deleting function which is this one and then we pass the note that the user is trying to delete so Dow do delete notes and then we pass event. note uh as this was as a suspend function we need to surround this with a view model scope orur so view model scope. lunch and then we put this inside side there like this and then uh let's go uh let's make this one the last one and then let's first try handling when they sort something so is sorted by date added. value is now going to be the opposite because it's we're just going to now sort it with the title so if this is true then we will sort it by the DAT they were added if it's false that's what we are going to do then we'll sort it by the title so very simple so is sorted by data were added do value like this I think I need a little bit of a typo here this a needs to be lowercase and now let's go to the save note uh function which is going to be a little bit I mean event which is is going to be a little bit big so first of all we want to create our note that we want to insert into the database so V note that is of course of type notes so that is equal to note let's import that import note and then we assign the title to be our state oh I actually did not create state yet so let's create that first so let's come here and create our state but first of all because our notes can be uh like changed from being sorted by the date they were added or the title we first start with that so let's create let's handle that right here so private V notes notes that is equal now uh I'm going to write something and I'm going to explain so is sorted by the date J were added do flatmap latest this one and then let right here and it it receives a sort which is the Sorting type so if I mean yes if sort so if that's true if it was sorted by the DAT they were added then our notes this these ones are equal to Dow do get notes ordered by dat they were added else dow. get notes by the by the title so uh basically we check uh this one which is the is sorted by date added uh if that's true if the Sorting is this one then we're going to uh assign the we're going to get the notes sorted by the date they were added else then we're going to get the title and then we'll write dot state in like this view model scope sharing started do while subscribed uh and then imp list so if none of those are true then we're just going to get an imp list I need to remove this and this I don't know what why they are there but yes so this is how we check this sorting and then if that's uh sorted by the date they were added then we're going to assign this as I said else then the title I mean this the one sorted by the title and then let's create our state so the state is equal to mutable State flow of course of note State like that and then basically this one is not not the one that we are going to use in our uh in our activity in our screen I mean but what I'm going to do is create another one so our state that is equal to combine so combine and then what I'm going to do is that our notes or our state can change uh based on these uh three things first of all this state so if any change happens in this State then our state that we are going to use in our screen will also change and we update itself and then the second one is is sorted by date added so if this as well changes and the last one is notes like this and then I'm going to open a bracket here and this will return for me State and is sorted by I'm just going to copy this oops I'm going to copy this one let's paste it here and then notes like that so in if any change happens in those three then uh we are going to update our state so state DOT copy dot copy I don't know why it's not suggesting that yet maybe because it didn't uh write uh state in shared with while subscribed but I'm going to write that so notes is equal to our new notes so like this and then right here I just need to remove this I guess dot state in and then a view model scope of course view model scope comma sharing sharing started do while subscribed and then a 5sec Time doubt and then note State like this I have an error here because I have an extra bracket there and in here uh I named this one the wrong way this is the one that I want to update so yes this is it now for our state we've created our state and our notes and now let's save the uh the notes so as I said this note is of type note and the title oops title title is state DOT value. tile. value again and then the description it's just duplicate that and then write description and here as well description and then the date added so date added is equal to system this is how we can get the current date so system dot Uh current time in milliseconds so this is how we can get the date and I should remove this line to to remove the error and then let's insert the note so again view model scope. lunch inside it we're going to call our upsert function so upsert the note we've created and then we want to update our state should move that bracket state. update it. copy and then we and we set our title to be an empty string again because we just saved our notes so we don't want the title to be like filled with any value anymore because we already saved that in our database so title is a mutable uh state of an UT string and the same for our description so description I need a little comma here like that so this is it actually for our view model now we wrote everything we need uh and now let's go to create our UI so the first thing is in our main activity we want to create our database first object and then we want to uh create the view model and and the factory for the view model because right here I'm not using any dependency injection like HS or something that does this for for us behind the scenes that's so I would have to create it manually because if I want to use that here then that's going to be too much for the video that's why I want to keep it simple so private V uh database like this by lazy and room do database Builder I'm going to pass the application context and my database so note database class. Java and the name of the T of the database so notes. DB like that and then I call. build to build the database and now it's creat my view model instance so private va va view model by view models and then of course my view model directory created notes view model and then in the uh here in the Constructor I create my factory so Factory uh producer and then object view model provider this one do Factory I know this is to much but I'm not using any dependency injection that's why I have to write all of this to create the factory override fun t view model uh view model create model class so model class that is of type class T oops T like this that returns a lot of code but what can you do that returns two t and it returns T I mean it returns notes view model and then I pass my d uh my DB I mean my database oops database. Dow as T so this is how you can create a view model Factory and then I just created my view model instance so let's get started with the UI now first of all I'm going to create my nav host controller so nav controller that is equal to [Music] remember nav controller and then I'm going to create the state so before I forgot that I forget that state by view model. State this one do collect uh collect as state like that and then let's create my uh nav host but let's import some things in here so let's create our nav host nav host and I'm going to of course pass my nav controller is equal to nav controller and the start destination let's first import this like that the start destination as I said is equal to uh my notes screen that I'm going to create right now notes screen and then let's create them so the first one I mean uh my first of course my screens are just composable so composable and then the road is going to be not screen which is of course this one and then inside it I'm going to call my screen and just create another one for the uh add new Note screen so here add notes screen like this and then let's create the first one so Power Note screen that of course will require state is equal to State before even I can create it and then the nav controller is equal to nav controller and the event so we know to know when the user did any uh does any action so is equal to view model on event like that and actually the same for our ad node screen add node screen so we're done with our main activity we've created our two screens now I mean we've created like the nav host with our two screens so let's just start creating the screens so the first one is of course the notes screen so notes screen that is just ay composable so composable fun not screen not screen I mean notes that's what I named it in the activity Note screen that of course takes state which is note State and then n have controller which is na controller and then the on event uh on event that is a Lambda function that takes a note event and it returns nothing so unit let's give our function a body and now let's start creating the UI so first of all is we want to create a scaffold like this so basically a scaffold just helps us put our uh top bar uh F in action button in the bottom bar uh Bottom bar I mean bottom navigation bar in in in the right position so the first thing is that we want our top bar basically this is the top bar to check it out this is the top bar that has this title and this sorting icon and this is the floating action button but we don't have a bottom navigation bar so to bar that is going to be equal I mean that is going to be just a row and this row will of course have a modifier I need to import Row first import row a modifier that is going to be filling oops modifier dot let's go to a new line. fill Max with because our top bar F the max width and then the height I can give it 55 DP import DP and then the background so background will be material theme dot color scheme Dot primary color for the background and padding of 16. DP and then I'm going to uh align the elements inside it like vertically centered so vertical alignment center like this and then I'm going to give a body content that is going to be inside it is going to be a text uh text that first of all just the title of the app you could get it by just saying string resource and can write r. string do app name let's import r or we can just hardcode it if you want to hardcode it but I'm not going to uh app name like this and now we have the title of the app and then our our uh our text needs a modifier so modifier is equal oops modifier is equal to modifier. we so basically to make the text with fill the all the remaining space after placing the button the icon and last or in the end of the row one if like this and then I can adjust this by giving a font size of 17. we use SP for text size and then TP for composable sizes uh and then the font weight I like I can make it semi bolt to make it look like a title so semi bolt and then it just create a little space here and then the uh color so color that is equal to material theme doc.on primary because as I said the background of this was primary now we're going to use the on primary color and then inside it we're going to have an icon button so icon button like this and in the on click of course this is the Sorting button and then in the on click I'm going to call the on event Lambda and I'm going to pass uh the Sorting event so in event. sort notes like this and then inside here I'm going to place now my icon so icon and I'm going to use an image Vector that is icons dot I love the rounded icons do uh sort you can't actually have this sort icon without uh having Library which is the extended icons library and in here on the description I can just call it U sort notes sort oops sort notes like this I can give it a size so uh modifier is equal to modifier. size I'm going to give it 35. TP and then the tint is going to be as well this one so this primary color so tint is equal to the primary color this is it for our uh top bar now let's create our uh Floating Action button so let's create our Floating Action button floating first need to put a little comma here floating oops this is the wrong place to put this right here so Floating Action button I'm going to use of course a floating action button and the on click I'm just going to navigate to the other screen so very simple right here I'm going to say nav controller. navigate to the other screen which is the add note screen this is its wrote and then I'm going and because I did not create an event for this basically you can create an event for this but I didn't uh I'm just going to Now set the title that we have in our state so state to title to empty strings I'm just going to handle this right here so the title is going to be an M string and then the description as well and then inside the floting action button we have an icon again an image Vector that is icons. round. ADD like this the content description is going to be add new note like that now let's go to create our list of notes first of all we need to use the padding values so that the error is gone and inside here we're going to use a lazy common so basically if you don't know what a lazy common is we could just imagine it as a recycle view in XML but way simpler like it's way much better and very easy and more simple than recycle View and then here in our lazy common I'm not going to use content instead I'm going to use content padding this one that is equal to padding value so that the error will be gone and then mod modifier that is equal to a modifier dot fill Max size so actually just to be clear this lazy common is being created inside the content of this skiold so fill Max size even if I say fil Max size this will be below the uh top bar and if we have any uh Bottom bar it will be above that so above a bottom bar if we have that and below a top bar if we have that so fil Max size and and then I'm going to give it padding so padding uh 8. DP padding and then I'm going to like remot the AR give it the content block I'm going to put my elements inside it space by 60 DP so vertical alignment is equal to Arrangement dot space bar uh 16 DB to put 16b of space between each item then inside our lazy Colum we're going to now create our items so items this one and the count is state. notes. size that will give us the index and then inside here I'm going to create our not my note item but I'm going to put it outside here so composable so I'm going to put in a different function fun um I'm just going to call it not item that will require the state so so this one in the note State I have an error here I just need to add this little experiment in annotation so that is gone so as I said we need this state in our item and our item is going to be a row that again requires a modifier to fill the max WID so modifier fill Max WID and then clip that item so it has round corners dot so clip dot round around the corners TDP and then the background of this item so background is going to be material theme. color scheme. primary container and padding padding 12. DP and then inside our row we're going to have a common so this is how this is going to look like the row because we have now a row that includes this section which has the title and the description and then the icon which is the Ling icon and then in inside this row we're going to have a common to put the title and then the description below it so common that takes a modifier to again make it fill as much space as we have after adding the icon so if we say we 1 F then it's going to fill all the space and then leave the rest of the space for the icon so modifier is equal to modifier. weight 1 F then inside it I'm going to have now the two texts text like this and the text is going to be state. notes index I did not pass index I'm going to pass it right now index of type int so index do title so this is it for my title but I'm going to decorate this of course I'm not going to leave it like this the font size is going to be 18. DP the font weight because it's a title it's going to be in semi bolt so semi bolt and the color material theme do color scheme do on primary container because the background is primary container and then I have an error here is and the error is gone let's copy this for the description but between them I'm going to put I'm going to put a spacer that is height 8 DP 8. DP and this is going to be the description and it won't be assumable it will be a normal text I a normal weight text and it's going to be a little small smaller than the other one and then the last thing is the icon of deleting a note so outside the common but inside the row I'm going to put the icon which is an icon button and then the on click I'm going to call the on event function that I again did not pass the event event Lambda function like this so inside here I'm going to call on event and I'm going to call the uh note event. delete note which is this one and I'm going to pass the icon that I'm trying to delete after clicking on the button do notes and index like this and then this is the on click let me just format that a little bit I don't know it's not Ming but this this is not how it should look like basically yes now after that inside this content block I'm going to put the icon image Victor it always gives me painter but I want image Victor so image Victor is going to be icons do rounded. delete and the description delete note like that and then I can always give it a size to make it like more beautiful so modifier size 35. DP and then the tint so tint is going to be material theme do color scheme do on primary container so this is it for my notes item I've created it and I'm just going now to call it inside my items here so note item and the state I'm going to pass State index I'm going to pass index and then on event I'm going to pass my event function and yes again from M this a little bit you can of course find the this source code in GitHub I'm going to put its URL in the description so this is it for my screen it's pretty big but yes this is the main screen and I'm going to import this right here now the last screen is to the add notes screen inside my presentation package I'm going to create the notes screen uh not a class it's a function can say composable function for the parameters they're going to be the same as these in the Note screen like that now let's create again a scaffold because we need a floating action button here so right here I'm first let me just create some space and then right here scaffold that is uh going to include a floating action button oops Floating Action button like this in the on click I'm going to send an event of adding a new note basically The Floating Action button is this one so when I try adding a new note this is this Floating Action button of inserting or updating a new note so in the on click I'm going to call the note event Dove notes and then I'm going to pass the title and the description of my notes so title is equal to state do uh title. value I'm going to give them their values right now and then description is equal to state. description. value and then uh right here I'm going to create my icon so icon image vector and it's going to be save or check so image uh icons I mean oops icon do rounded. check check this one and the description the content description is going to be uh save note this is it for the icon I can format this a little bit and right here I need actually after clicking on this I need to go back to the previous screen so nav control. pop backstack to go back to the previous screen and now inside the content of my scaffold I again made my padding values I need to use that so that the error make the error gone so I'm going to have a common here because I have two text field right now I mean right here I have two text Fields one on top of the each other so I need a common for this common and this common we need of course a modifier so modifier dot uh padding oops not that about padding and I'm going to use the padding values and then the F Max size and then inside here I'm going to have two text Fields so let's create them text field the value so let's just put this in different lines the value is going to be my state do title do value and the on value change that's where I'm going to uh assign now a value to my State title value that is equal now to it so whenever I make a change I assign the new change into to my St into my title that is inside the state and this is going to require a modifier uh to fill the max width so fill Max with oops it not call modifier do fill Max withd and do padding 16. DP import DP and then uh I'm going to stylish this a little bit I'm going to use a Tex style so I'm creating this I could have created the UI previously and then just show you how you can call events but I'm creating this so that you know how you can also create you are using JP compos if you are new to it so I'm going to stylish a text inside a text field we use text style and then you can pass any normal attribute attribute that a normal text would have so font uh with need to First Call the function that is textile so I made a mistake here Tex stle and I need to remove these brackets so I open this one so inside here that is equal font weight that is equal to Su bolt that's what I'm going to use and then the text size so font size 17. import oops import is what's going on here import is I don't know why I did this but format this and then a place holder which can be described as a hint in a text view previously in XML so to use a hint here we just use placeholder let's put a little comma there Place holder that is just a text a normal text that says title like this and then error in here I need to add this little experimental uh annotation and then copy this for the other text field which is going to be used for the description and then this one won't be styled because I'm just going to leave it the way it is and then this is going to be description for the placeholder disk and then this is going to be description as well and this one as well so I guess this is it for the uh ad notes screen and actually this is it for the entire app I'm just going to import this this is for main activity I have an error here let me see let me just remove this and make sure that my view model is okay everything seems to be okay and now let's run the app and hope everything is working fine so this is the previous one I'm just going to close it and wait for the grle build here it is now running this is my app and let me just open the app inspector to see any changes in my database so this is my notes database right now it is empty let me try adding a new note I'm just going to call it a I'm going to call it test a and save that oops I'm not saving it let me just see what the problem is and I'll be back so after a little bit of debugging I found the problem in the ad Note screen in The Floating Action button I actually didn't call the on event Lambda so I just need to call that and then pass the event to that Lambda and now run the app again and the problem should be solved so go to the app inspection like this and let's try adding a new note so let's call it B test B and save so it is our note let's add a new one call it C for example oops C and see test then save that let's add a new one call it a now and test a and save that let's make sure that we have our uh items or our objects in the database yes they are there uh this these are the basically there is no one because when I was debugging I created one this is the date they were added in this is the description and this is the title so this is our table we can of course sort this so right now they are sorted in the date they were added and if I sort this now alphabetically a b see so sorting is working fine deleting is working fine if I close the app they open it again I find that my notes are still there I can still sort them and if you want to do something like this as in the uh app that I showed you at the beginning the video when I open the uh keyboard The Floating Action button actually goes uh above the keyboard you just go here to the main activity and then you write window soft input mode and I'm going to write adjust resize so that it adjust the position of that Floating Action button so when I try adding Now new note so if I give it like a description here as you can see the floating action button goes up here and if I save here is my notes and yes this is it for this video hopefully you now you understand how you can use room it's very simple it's easy it's just a bunch of a bunch of annotations and you then create your uh database uh class with an annotations again and uh that's it actually for this video thanks for watching see you in another one and bye
Info
Channel: Ahmed Guedmioui
Views: 7,537
Rating: undefined out of 5
Keywords: android studio tutorial for beginners, android studio project, android studio app development, android studio app, android studio app project, kotlin android tutorial, kotlin tutorial, kotlin multiplatform, kotlin full course, jetpack compose tutorial, jetpack compose android, jetpack compose mvvm, jetpack compose state, jetpack compose viewmodel, jetpack compose vs xml, jetpack compose app, api key, jetpack compose animation
Id: 5pjdE2wnJ0s
Channel Id: undefined
Length: 56min 47sec (3407 seconds)
Published: Wed Nov 08 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.