How To Use SQLDelight Cache Database in Compose Multiplatform App | How To Add Offline Support

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi guys welcome to cing ambitious and in this video we will be learning about using SQL Delight in compos multiplatform right so this is a single app we are displaying the products from the uh Network only so what about if we want to add the offline support here right suppose if internet is not available there and we want to still we want to show records so for that we need to save the record somewhere in the app right so for that we will be using the SQL Delight here right so we can use real as well but here we will be using the SQL delight and maybe in some other videos I will be covering the real as well right as local DB so how to add the offline support so this is the all about that right so let's continue with that so first of all let's you can check out its documentation so let's check that and few steps are there so let's start integrating it right uh one thing why we should use use the SQL Delight so basically SQ Delight generates the type safe cod in apis from your SQL statement so it's directly basic basically depends on like we are writing the SQL statements from that it generates the types of API so we don't need to worry about the types as well right so directly it generates the type of the record from the table like table means where we are writing the statements from that it's rating the Ty directly right so let's continue with that um let's add this [Music] so step one and then let's go to second part so basically after this we need to define the SQL Delight block as well so so it will specify some configurations there you can specify it here step two so yeah SQL Delight step two okay but it will be picking it picking up it once we'll be sying it right let think it so thinking it done and you can see now it's showing it databases we can specify we need to create the database name of the database and this is the package uh so let's check out the package of our app and we can accordingly specify that we can keep that this similar right okay and yeah so now let's move on to the another part so now suppose this block we have added there but now this is just for the configuration part now the main step comes here we need to create the SQL Delight directory right so that will be inside the where we have inside the common man we have this scotl right so at the same level where we have this scotl package here right so at the same level we need to add SQL Delight directory okay and now let's add one package or maybe we can directly copy it and add it yeah yeah that's then and and so now we need to create a SQL Delight file so for this you can install the SQL Delight plugin then you will be showing this suggestion but we can directly create simple class file as well so just create a simple file name it F bc. sqsq Type file you need to create right so yeah you can create it now let's sync it and we'll be moving to the next step then so we'll be writing the all the queries here right suppose we are the fetching the product so we'll be creating the query for product table right it'll be doing that in a bit okay so so before that let's uh start adding the drivers so basically what happens so suppose we have written here the uh queries right just for example suppose we have written the queries here or you can say statements so what will happen is so after the project is compiled so the generated Cod code will be stored in the shared build generated folder actually it mean this one is we have this not shared but this one in this project structure it is not shared so build and generated here SQL Delight you can see everything will be generated here right so what happens is from these St statement so we can we can write statements actually we can name it statement that is the proper word so we'll be writing the statements here like create insert update delete right and from those SQL Delight will generate a database class right so and then database class will be generated and then what we need to do is so so if we want to use that generary database in your code we need to add the driver dependency basically so what will happen we will write state statements here then from those statements database will be generated and then that database will be used via drivers right for each platform we need to create drivers so now we'll be moving to the next step so let's add the driver dependencies we'll be writing the statements then later on okay so if you go here defining the schema constructing driver instance yeah you can see it here so let's uh basically first of all we need to create it inside the common main yeah this one so inside common mail let's add a directory here database and then let's add one new file so let's name it simply um D driver Factory okay and yeah this is the expect class and now we need to provide the implementation for this because so drivers will be different for each platform right that's why we created the expect class and we will be providing the actual implementations for them right so that should be at the same package level so inside the C we have database directory the same thing we need to create if we just copy it inside the other source sets right you can see so um that was inside where yeah inside this cotlin database okay and yeah so this cotl inside cing we have database right here it'll be going yeah so this one is there and here what we need to do is we can make it actual and actual so uh one thing forward so this function will be suspend actually suspend type I'll be explaining that why it is so so spend so then we will be adding the okay I missed one part actually we need to add yeah these drivers as well I missed that part so you should move to this part then and then we should create the drivers so let's add first of all these dependencies for drivers so if you go to the Android main y this one is for Android this one is for iOS okay and then this one is for desktop M okay okay so now yeah so for one it's remaining so let's go to the web for web let's go to the SQ JS for that we need to step add this one extra step as well uh we can make it generate a syn so it will be basically uh providing the asynchronous implementation so right it means it will not be blocking was right so then let's move on to the yeah creating the drivers for this yeah this one there add this to the JS main actually that we have not added yet oops wrong this one is for the driver class I was a little bit confused so we need to add these dependencies let's add them uh the one and then we need to add these two as well for the SQL JS web worker right so yeah these dependencies we need to add so yeah let's first sync them now those dependencies are done now let's start creating the drivers so let's provide the implementation for them so um inside the Android side we can just return Android SQL drivers and inside this app [Music] database it should show okay uh what is the name of the database we have specified let's check that let's make it t database let's now clean it because it has already generated that for the database name but we want to rename it as like G database it will be easier database do schema dot synchronous so it will be automatically it requires basically if you go here what it will be doing is it will be creating the DV there right so implementation will be there okay SQL schema it will be generating the SQL schema because if you want to um this because this requires synchronous implementation of schema so that's where it will be providing this synchronous function will be providing the synchronous definition because this will not be synchronous this this will be synchronous right if you see this is a sync value but now it will be making the synchronous value right and then we can specify the app DB M DB maybe the name okay [Music] and why it's showing this okay uh one parameter I think we are missing it requires context as well that we will be accepting from the okay now it's fine and similarly let's um add it inside iOS Main so where it was inside this database directory and then let's [Music] add driver [Music] Factory and then this one and let's remove Mo this this is not required here and here we will be returning [Music] the native sqi driver right and it does not require U context okay so this is it and now let's now let's add it for the desktop it was inside the cine okay and here we will be returning the jdbc sqli driver and what parameters it require [Music] it does not require this it requires URL properties so these are few things which we need to set up so it will be setting up the jdbc sqlite right so basically the URL for sqlite if you have worked with the Java so have connected the uh database connectivity inside the Java so you may be knowing about this jtbc sqli drivers okay and so actually we need to do one more thing here have database do schema do a wait create driver return drive it will be creating the schema here right a create it is a wait create suspend function that's why we have made it suspend right so now let's add the similar thing inside the JS as well so here what we need to do is if you see here we were using that yeah this point so let's create this and okay and then add this schema this will be the so this part we are doing separately for JS and desktop but for iOS it was already being passed here directly right so that was some change in implementation the way of implementation right so now we have specified the drivers now let's move on to the next part so now we will be creating the um one Deb helper class basically right so so inside so why do we need this DB helper basically so I'll be explaining that in a bit so it will be accepting the driver Factory here and then we can create One DB variable Here app database and let's make it null initially then we can use mutex here I will be explaining that so mutex is basically uh if you have worked with the uh multi- threading like synchron ization suppose multiple threads trying to access some values at the same time so we need to provide some kind of synchronization so for that we will be using the mutex so it will providing the thread safety so that no two threads will be accessing the values at the same time right in cine we use this way so now so here what we'll be doing is I'll be explaining this thing to you first of all let's create one method here suspend fun it will be the create DB right and accepting the driver Factory and returning the app doab base okay this method will be creating the database right so here we will be checking the um sorry we will be returning the app database so driers is equal to driver Factory dot create driver right we'll be returning this and then so because this function is suspend so that's why this function is also suspend and why do we need this helper class is basically what happens is so we initialization process is now becoming suspend right so suppose at this some initial type when we we will be patching from the pay we need to check if database has some records at that time so we will be needing this database class right so if suppose anyhow it it's not initialized at that time because it is as synchronous suspend right so so if you know uh how a synchronous execution so it it it may suspend the code so by the time we will be needing that suppose it might not be initialized so that's why we need this DB helper class basically right so here we'll be creating the any result of any type one generic function so we'll be creating a [Music] simple method here like with database and that will be returning the result generic parameter right it can be anything if we are returning some records we can will be the list of those records otherwise it can be unit as well right so we can Define it directly with M Tex oops M text Dot with log yeah okay okay cool so now if so this check I be explaining it now it will become more clear to you if DB is equal to null because create DV then we'll be creating the DV here and passing the driver Factory we can make it private as well okay and then we will be returning the block okay oops I forgot to add so there will be a block here as well so that block basically a suspend function actually right that will be accepting the app database parameter and returning the result right so that's why when we will be calling that block here so we will be returning the value directly which is being returned by this block right and let's make it where so I'll be explaining this suppose so this this process is asynchronous asynchronous means it means we will not be waiting for this result right so it's a suspend function actually it will not be blocking so if you know about asynchronous functions so then might be getting this idea why I'm doing this POS at the first time we'll need to use this DB and at that that time suppose it is not initialized right so then there is a problem it will be null so you will not be able toess it so that's why we are making this suspend function so that we can access it in a suspend way right so a synchronous way so that's why we have used this so that every time we will be using some queries or doing anything with the database we'll be using this fun function with database it will be checking if it is null that it will be creating DB only if it is null if it's not null it will not be creating it again right it will be just directly returning the response of our queries which will be this block right I'll be explaining this while I will using this right because otherwise while creating the database you might face some problems there because this is suspend functions you can try out and you will understand about that if you directly try to create this uh database initially then at some point we you will get some issues with the like implementation you will get confused how to implement those things because it will be a synchronous function so it might get null at the initial time so you might not be getting the desired results so that's why we have created this helper um method there okay so now this is done and now let's move to the sorry and now let's move to the another class so that is the database class but before that I will be moving back to the um app database. SQ class right so here we will be writing the queries now suppose create table for name of the table is product and it fields are integers primary key not n and the next field will be title and it will be the text type so for the string types we'll be using the text right so what I have written here it will be the integer it will be like this okay so text and we want it not null and then suppose we have image field it will be the URL and then we have price field so that will be the double for double we use the real here real type okay and so then uh which fields are remaining ID integer price and then let's say category not n and then the description nextext not n right okay yeah it was the issue with this last comma so it can be just text and it can also be text okay so now let's create the insert product method so it will be creating the insert product method in the database class I'll be showing you while we'll be using it so that's why it's called save type save API so it's generate the methods with these labels right insert into product okay P capital okay insert into product ID title image i title image price then category then description right and values inside values it will be accepting these from the parameters how many are there five okay okay cool and let's terminate this statement okay so with this label the same name with the same name it will be creating one method there in the database right suppose similarly we can write this method as well remove all products okay delete from product these are just simple SQL queries if you know my SQL SQ then it will be easier to understand select all products okay select all products so then select product what it will be we will be fetching the all fields of the product all Fields so this product table all field for Star right so we are specifying here we need to fetch all field means star here from the product table okay right and then we can make it [Music] from product Okay Okay cool so these queries are now done so while I'll be rebuilding it I will be showing you like these methods are already there it has generated those methods right so I'll be showing you that let's Sy it and now let's move on to the next part where we'll be creating the database class okay okay and after database class we will be adding the few data sources as well I'll be explaining that point to you so let's create the database class now Okay so let's go here database let's create one class database okay and inside this database class what we'll be need is it will be accepting the DB helper okay and another one can be we can directly even we can pass this scope as well there as a constru this it's a good approach actually we should pass scope or dispatchers maybe as a Constructor parameters it makes testing uh easy for them so we can create just let me write single queries here you will understand it better scope do launch and then with database DB helper do with database so now we'll be it will be providing the database to us and we will be using that database cuz now we don't need to worry about if database is initialized or not or anything because this method will be taking care of all those things here right and whatever we will be writing inside this method here here we will be writing and doing returning anything so that will be eventually return from this block right and that we can um return if you in case if you want to return some values I be coming to that like while we'll be fetching the list and returning that so I'll be explaining this thing at that time it will become more clear right so inside this clear so what we need to do database dot okay let's make it I have database queries this field is there we need to use that actually database doab database do queries do so you can see now these are the methods with those labels right if you see removeable products and you can see implementation of these these are just simple queries we have written already there similarly it's the insert product this is also the label there and this is also label there right so these methods we have written in the labels in the app database. sqd it has created all the implementations for them right so this is for it and now let's create some other function that will be the suspend function get all products okay and here also what we'll be doing is we are items or of list of product okay cool and now what we'll be doing is well result so we will be using the async here so that we can await its result right because we need to fetch this result and then we need to return that result dot await so whatever you'll be returning from here that it will be returning from the this method as well right let's make it return type as well because we'll be returning all the records from the database right so now let's uh assign those variable oh sorry like assigning the items variable as whatever we will be fetching from the database database dot database queries dot what we need to do is select all products right so and now select all products it requires this m right so for that we can actually what will happen is we are returning the list of product right so this method so what it's doing is query of product right and this product is if you see inside the SQL Delight generated file right so we need to map these file so this is the product class from the DB and but we need to return results and this our data class form right so that mapping we'll be doing here for that we can create one method here actually so let's create one method here map product selecting so while be selecting from the DB let's map it so it will be requiring all the [Music] parameters if you see here these parameters this MEAP it will be requiring in the same order right okay we can add them and then what it's doing is returning the from the DB product it will be returning our product class right so let's return product and ID equal [Music] to ID do 2 to in because it's it will be turning as long but inside this we'll be using the in we can make it long as well required then we will not be needed this conversation conversion price and then the category and then the description and then the title and then image I guess also there so this is for the mapping and we can pass directly reference of this method here if we see what it's showing is okay let's check it okay so this will be returning the query right query of type like query of product but now we need to await as list so it will be returning the list from there like right we need to use this method okay so execute as list is also there but that is not the asynchronous right we can use a way as list that is synchronous right you can see suspend function and if I do execute as list it is not suspend function it may Lo the um thread okay while catching so now return let's item Okay cool so now this is also done and now let's add one more method there that will be the we need to create products as well right from the uh response of the API so so in this um we will be getting the items list of product and it will be just saving in the TV we don't need this and the here what we need is don't need to return anything so here what we'll be doing is we'll be inserting the product so items dot for each for each we will be uh inserting the product and again for that actually we need insert product first then we will be creating the create products so it will be just accepting the product type here and for from that product we will be we will be inserting the product and that again insert product that method we created there and inside that method we can pass all the parameters here item do ID do to string okay and then title it's not to Str it's long actually inside this type is long right so yeah and then [Music] title title and then image image okay and then the [Music] price price uh will be the price dot to double okay okay price is double and here double so it's nullable so we can just default value there okay then the category it will be the item do category then the description so this is for the insert is return now we'll be calling this for all the items here by passing the item here okay cool so these methods are now done now let's creating the two data sources because earlier we were fetching the records directly from the um ear fetching the record directly from the network but now in the repository we'll be using the two data sources for Network part we'll be using us the remote data source for local database query you will be using the local data source right let's add those data sources data source and here let's add two classes local data source and let's give it name for products local data source and it will be using the database database okay and so what it will be doing we will be doing here so get all products so we'll be returning the return database do get all products fine it will be of type product okay cool and we can make it private as well and then we [Music] can clear DB as well so it will not be returning anything we can just clear database okay it will be removing all the products okay and then let's create save products okay so it will be accepting the list of products and then it will be creating the products from the L and saving inside the okay and let's just log as well here so that it will be easier to understand for us okay so this this is done now and local data source is also done similarly we can create the remote data source okay so this will be accepting the HTTP client it will be fetching the records from the network only right that's why we are using the HTTP client same method will be there and that method we can move [Music] there so we can make it here okay cool and this one we don't need this one also we don't need right from Network we are only patching the products right now next part is we have created these dependencies so we need to use them here and also um products local data source and remot data source okay so now we need to make changes at dependencies as well because now we are using the dependency section as well there and if you want to um so if you want to know about how we did this dependency injection you can check out my other videos on YouTube so those are the like dependency injection in sorry so if you want to check out how I added these dependencies there you can check out my my another video so that is dependency injection in compos multiplatform so you can check out that video you'll understand how we did this dependency injection so now let's create one another module actually similar to this network module we can add the cachier module there okay and inside this caching module what we need to provide is so we will be providing the so we will be providing here the DB help those and the database and inside database we have two dependencies if you see DBL plan cortin scope and then that cortin scope we can just create that one okay so so we can that we can create that here itself actually so it will be [Music] cortin context type and here we will be returning the this code routin scope this one and it will again expecting the one parameter that is I WR it wrong actually so this will be the C in context and here we will be returning the dispatchers okay okay and then this coordinance context is required by this as parameter right so here we don't need this it will be getting this cording context like this dispatch don't defa right in the scope this will be the scope which is required here okay cool now the dependencies are done there now let's add these before network module and let's add those dependencies here as well update we can update these parameters and similar to these we can add local data source and it will be getting requiring one dependency database that we have already defined here and similar to this more data source this is done now dependencies are also done and home repository we need to make few changes here basically so now what we need to what change we need to make here is so suppose inside this get product API first of all let's accept this parameter here Boolean let's give a default value false so because there will be two cases we will be patching from the network either records are not in the local DV or we are forc reloading right so in those two cases we will be doing this right so now get products this method will be called again require this parameter okay so we'll be making that here passing this parameter there right and inside this what we need to do is so here first of all we will be checking the cashed item so that will be from the local data source right get all products right so if now we'll be returning actually if cached items dot is not empty right it not empty and not force reload as well right suppose if um this is not empty we have records in the cat items and we are not reloading Force loading right Force loading means we we will be getting the record from the network but we are not doing that so we need need to make sure these two parameters these records are not empty we have something in DB and we are not forc reloading in these cases we need to rec return cach items else products local data source sorry more data source do c all products dot also we can specify I clear tv as well here okay and we can save products as well okay after getting these from remote data source like from the API we saving in the DV as well right if they are suppose this will be happening in two cases either we are Force reloading then also it will be fetching from the network and clearing the DB and saving in the DB right and suppose this item is empty suppose we are catching first time then also it will be triggering right okay so now let's use let's make it private and this method we are already using here here so yeah now it's done actually let's try to run it and we will be checking in the logs if everything working is working or not so we will be adding some logs here as [Music] well just for understanding let's make it like this okay and let's make it cach right so that we'll be understanding from where we are getting the records Okay [Music] cool so if we see and go and see in the logs some dependency issue might be there let's check it database driver Factory okay so we need to make few changes we need to provide the database Factory as well so that we'll be doing the app specific code so for this we will be doing inside this main activity okay single so this driver Factory is required by actually if you will see in the cashier module so if you see this DV helper it requires driver Factory so we have not specified that in the coin modules anywhere right so because that requires for Android it requires context so that is the expect class and we will be providing the actual implementation so we'll be returning it from here driver Factory so it will be automatically picking up the [Music] implementations from the specific platforms automatically right and then similarly we can add it inside the IOS as well right okay let's specify it there as as well it will not require this it will be using the implementation for iOS and similarly we will be adding them to the another like for as and then for jvm right now let's try to run it if you see from Network right first time it's searching from the network let's try to rerun it yeah first it was from Network now you can see it's from cach right even if I clear logs you will see these record records are from cach right you can see from cach from no network is there right so now it's fetching from the cach so if we will be passing the force refresh so that things uh those things we will be implementing according to our logic when we need to up uh Force reload we can reload then it will be patching from the network and updating in the TV right so this is done now guys and now let's check it for other platforms so in the iOS side as well so if you see we have some issue in the iOS side some binding issue is there yeah ex I have experienced it before as well so for that what we need to do is we need to add one thing actually let me show you we need to specify this issue I was faing earlier as well so you can check out this link as well posting in the description so we need to add actually this Linker flag okay from the xcode so you'll be doing here other maybe Linker okay linkers we might be getting [Music] somewhere yeah here it is so here we can add that and now I think we should be able to run it if you see we are able to run it now from network if you C from Network okay cool from from cash is not there right and let's run it first second time yeah it works you can see from cash Okay cool so now second time it's not fetching from the network it's fetching from the so even if you want to test it like if you want to just confirm this thing so let me explain this so let's in the Android app I'll be showing you like turning of the internet and then I'll be showing you still it will be able to F the records so first of all let's check yeah from cash so just in case internet connectivity is not there I be explaining covering that case as well yeah you can see now there is no internet here but still if you will be loading it it will be picking up the record from the cash you can can see so this is picking up from the local cash right yeah so we can enable internet again okay cool so this is for iOS oh sorry Android and I have showed for you showed to you for IOS as well now I'll be showing to you for desktop as well okay let's stop all first yeah yeah forx code it was only this much Ro now we can close it can see for desktop as well it's working but for this I think let's to it if it will be picking up from the cash actually will be every time fresh install so here we will not be able to see that effect yeah you can see it will be every time from Network because if we are not able to refresh it right so similarly it will be on the web so yeah it will be working on the web as well so saving the records in the TB okay so guys this is all about this you can try to run it web as well so here we have implemented the SQL Delight here right so I hope you guys now have an idea about how we can use fetch the records from the network and Save in the local DB using the SQL Delight so this is all about this video I will see you in the upcoming videos so and please and humble request if you are new to my YouTube Channel Please Please Please Subscribe and if you are existing subscribers please please please like share and comment that will motivate me to create more videos related to this so I'll be keep sharing my experience with you guys and I hope you have found this video useful I will see you in the upcoming video till then bye-bye take care have a great time keep [Music] cing
Info
Channel: Coding Ambitions
Views: 1,494
Rating: undefined out of 5
Keywords: kotlin multiplatform tutorial, compose multiplatform tutorial, kotlin tutorial, kmm tutorial for beginners, compose multiplatform app, kmp tutorial, android studio, kotlin multiplatform android studio, compose multiplatform cache database, sqldelight in compose multiplatform, compose multiplatform offline support, using cache database in compose multiplatform, save data locally in compose multipatform, sqldelight statements and drivers
Id: iRlfJcnLFF8
Channel Id: undefined
Length: 63min 11sec (3791 seconds)
Published: Thu Feb 15 2024
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.