ObjectBox - Fast Local Database for Flutter With Optional Sync Across Devices!

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
when you're choosing a database you're going to use in your next project it's good to make wise and informed choices object box is a very fast no sql local database for flutter and also for native android and ios with an intuitive api rich support for queries and relations plus you can optionally keep the database synced across multiple devices without any hassle on your part this whole tutorial is actually brought to you by object box their local database packages are completely free and open source and they are extremely pleasant to work with as always i only work with companies whose products i personally believe in and object box is precisely that kind of a great product [Music] hello welcome to riso coder where you're getting prepared for real app development so that you will get freelance clients or a job and be confident about the apps you build so subscribe and hit the bell to join us on our quest for becoming in-demand flutter developers in this tutorial we are going to build a shop order application which is going to show orders of respective customers as you can now see on your screen you're going to learn a lot says enough of entities relations ordering of data reactive queries and all of this cool stuff first we're going to focus only on the local database functionality and then at the end of this tutorial i'm going to show you just how easy it is to sync your data across multiple devices with object box sync so the app we're going to build is going to look like this again at first it's going to be purely a local database but then we're going to also sync the data across multiple devices so what's going to happen is that now and inside this app i can add new orders like this and as you can see because we are already using sync in this already finished app these new orders display both on the android emulator and on the ios simulator simultaneously so that's extremely cool i have a local object box sync server running on my machine here so we can add new orders and it's going to add orders for a customer in this case the customer is called joe o'hara we don't have any real input forms for the name of the customer and for the price of the order we are just using a package called faker to generate fake names fake prices and all of that so that we do not need to worry about user input we can change the customer for whom we are adding the orders or who is making the orders to be more precise by pressing this other button on the app bar so this is going to change the name of the customer for whom we are adding the order so boom now the order is added for dr brooks stauba you know and of course we can do the same on ios change the customer boom then we can also delete individual orders for example here for howard golovsky delete that that's also possible and we can also sort these orders based on their id so either descendingly so either ascendingly or descendingly and also ascending and descending sorting is available for the price as well lastly when we tap on a customer name for example this solid at collins we're going to see only the orders made by this precise customer this is something where we are going to use relations which object box supports so they're going to come in very handy also we can show all the orders for vern debert like this we're going to show them in a modal bottom sheet and the underlying widget which we are using here which takes up this whole screen is called data table this is a core flutter widget which we are going to be using you don't really need to know everything about the data table widget which comes with flutter in order to follow this tutorial but i would recommend you to still check out the data table documentation from the official flutter docs just so we are on the same page actually all of the links to different kinds of documentations and all of the code is available from the link in the video description over at that link there is the whole written tutorial which accompanies this video tutorial on youtube so over there you can find all of the code written in this video all of the links and overall go through this lesson at your own pace additionally from the written tutorial you can also grab the starter project which is going to contain the following code so that you do not need to start completely from scratch and we are going to only focus on object box package in this tutorial so the starter project contains this main file which sets up the home of the material app to be a home page this home page is just a simple stateful widget which depends on faker and then this stateful widget contains a app bar with two icon buttons which look exactly like this these two icon buttons and then it has an order data table which currently doesn't show anything it's just a placeholder this order data table already has a callback for sorting but again we are going to implement all of this in this tutorial and then also from these two icon buttons on the add bar right here we are calling the set new customer method and also add fake order for current customer methods and you could see them already demonstrated what they do right here currently they don't add any customers and don't add any orders they just print something to the console using faker but we are going to use precisely this faker person to generate a customer name and then create a customer object and then put it to a database for now we are just printing everything we just have placeholder code everywhere as for the order data table which is where all of the data will be displayed all of the orders it currently looks like this so again i would recommend you to check out the official documentation from flutter.dev for data table if you are not completely familiar with this widget yet but anyway this data table has a on sort callback which we are calling whenever we press on the individual columns as you can see right here when we press on this column the on data column sort callback will be invoked and we are going to implement that data coming from the database will be sorted based on either id or based on its price so that would be it for columns they just define the number of columns and the name of the columns but the actual data all of these orders are going to be displayed in rows in data rows in the actual ad once we implement it the data row will contain the id such as 13 then the customer name such as alva bayer then the actual price but for now we just hold placeholder strings in all of these data row data cells but this is where the actual data coming from the database will go and also when we press the delete data cell we should delete the order from the database and lastly tapping on the customer name as you can see here should show the modal bottom sheet and display the tabbed customers orders again this startup project is available from the link in the written tutorial and now that you know what kind of an app we are going to be creating and where you can get the startup project and how it works let's start implementing the app firstly we need to add dependencies and there is going to be a bunch of them so let's open up popspec.yamo and make sure that your sdk version of dart is 2.12.0 so that you have the non-nullability support and we are already depending on faker which actually is already available with version 2.0.0 then we'll also need to depend on object box object box flutter lips and path provider for the regular dependencies so let's add all of these dependencies in here like this so currently the object box version we are going to depend on is 0.15.0 the same goes for object box flutter leaps very soon there is going to be the version 1.0.0 and this 0.15.0 is fully compatible with the first stable 1.0.0 version so even if you go to pump.dev like this and search for object box and you're going to see that there is the 1.0.0 version that's completely fine this tutorial is still going to work with that version also links to object box are in the video description and to all of the libraries there are always links in the written tutorial we are using path provider because we need to be able to point to a directory where it's safe to store persistent data on either an android device or an ios device and path provider will allow us to get that directory easily then for dev dependencies going to depend on build runner because object box works with code generation and then we are also going to depend on object box generator if you do not want to be typing out these dependencies manually you can always grab this code from the written tutorial the dependencies have now been successfully gotten and i would like to start the app we are currently developing right now but before we can do that we need to go ahead and edit the native ios project if you are developing for ios and you are on a mac and also since at least i am going to be using the object box sync to sync between multiple devices at the end of this tutorial for sync i also need to bump the minimum android sdk version to at least 21. if you are not using sync you will not need to bump the minimum android version but if you are it needs to be at least 21. so let's go ahead and do that we are going to start with ios so again this only applies to you if you are on a mac and you are developing for ios if you're not feel free to skip this section so i'm going to right click on this ios folder and say open in xcode here we go and we are going to need to bump the minimum ios version [Music] to at least ios 11 this whole xcode ui is very small so i apologize if you cannot see everything properly on youtube but we need to go to runner here then targets runner scroll down and somewhere in here if we go to build setting actually here on this tab above we're going to scroll down and we will see ios deployment target right here so you want to edit this bit and set it to ios 11.0 so this is the minimum version which object box supports and then additionally we'll need to go again to runner but not targets run about project runner and here let's again select build settings select all so that we see all of the settings and we're going to edit all of the way above this architectures bit so click on this architectures and object box supports only 64-bit architecture that's completely fine because all of the ios devices where iphones or ipads from the last few years already support 64-bit architecture but still you need to indicate that to the native ios project by changing this setting in xcode so click on this architecture's value and select other and now we want to replace this arcs standard so double click it and we instead want to write here dollar sign and then all caps arcs underscore standard underscore 64 bit and now you're good so you can click away and the architectures are now going to be standard 64 bit with these two steps finished you can now run the app freely on ios and it's just going to work so we can close the xcode but what we also now need to do at least i need to do it because i'm going to be showing you how to work with object box synced over the end of this tutorial is to go to android app and then build.gradle here and i'm just going to bump the minimum sdk version to 21 so at least i need to do this you may not need to do it depending on where you are using sync or not with this out of the way let me actually bring the android device here so that we're going to be developing on android throughout the throughout this tutorial and let me run the app on android so currently there is not going to be any data displayed because we are still using just the placeholders from the starter project but we are going to change that fairly soon so this is how the star project app looks like it contains the data table it's clickable we can sort of sort based on the number and on price but it doesn't really do anything because the data is just placeholder hard-coded string values also when we tap on changing this customer icon and open up the debug console we're going to see that we have printed emea johnson and miss chloe murphy fourth for some reason right and also when we add a new order we are going to see its price which is randomly generated using the faker package so we are shortly going to use this to actually create customer objects and order objects that are then going to be put into the object box database by looking at this let me just change this number column name to say id so let's go to order data table and here in the data column where it says number let's change this to id so let's first create the classes that are going to be created and then put into database instead of just printing these uh messages into the console from the home page methods set new customer and add fake order for current customer object box works with entities these entity classes allow you to work with just nice regular dart objects from your flutter app and then it's the object boxes responsibility to take these nice dart classes and convert them to something which is then stored in the database but as for you as for the end developer you do not care about how the data is really represented on the database and that's the beauty of it so you can just work with nice regular dart classes we are going to have two of them in this project one is going to be a shop order and the other one is going to be a customer so let's create under the lib folder a new file call it entities dot dart and we are going to create first a class shop order this is going to hold a price and also each and every entity that's going to be used within object box database needs to have a field called id of type int so int id this is an absolute necessity then as you can see beside the id and the price there should also be a customer name present on the order but we are actually going to handle that via a relation to another entity which is going to be a class customer right so we're not just going to put somehow a string customer name directly into the shop order no we're going to point to a customer entity inside a database we're going to handle that later for now let's just focus on all of the fields besides those ones which represent a relation so these two fields are then everything besides relation fields which is going to be on the shop order so let's now create a constructor right we're going to create sharp order and then these are going to be named parameters so we would say required this dot id and required this dot price right yes i mean this is kind of valid but actually it's not our job to populate the id it's the job of the object box library to populate it whenever this data is stored in red from the database so we don't need to make this id a required parameter it can be optional and then we are going to provide a default value of zero whenever we do not specify this id ourselves when we are instantiating a shop order from our app but this id again will be populated by the object box package every entity needs to be annotated with the add entity annotation which comes from object box so that code generation is going to recognize that this class is actually an entity and that it should generate code for this class let's actually kick off code generation so we're going to use our most favorite command which is flutter let's first clear this and flutter pub run build runner watch and run that you can also copy this command from the written tutorial and the code which is going to be generated by object box generator is always going to be at the root of the lib folder right here inside a file called objectbox.g.dart of course we need to first save the entities files for the g.r file to be generated so here it is and also we have just generated object box model.json so this json file is used from the object box sync for syncing data between multiple devices which i'm going to demonstrate toward the end of this tutorial and then the object box.g dart is simply used within our local database if you're putting your project to source control which you probably are it's quite important to keep this objectboxmodel.json in your source control so you want to check it in but as for the g dart file as is kind of usual with generated files you do not want to put them into source control so let's actually just go to git ignore and somewhere around here maybe all the way down i don't know here in flutter dark pub related we're going to say that we ignore anything that is dot g dot dart boom and now this objectbox.j.dart will no longer be checked into source control but this object box model.json is going to be checked that's quite important so let's now also create the customer entity so add entity and it's going to contain int id then string name and it's also going to have a constructor customer let me just actually use a dart data class extension in vs code if you don't have it and you are using vs code i highly recommend it dart data class is the name of this extension dart data class generator and you can always copy the code from the written tutorial so again this id doesn't need to be required and we are just going to set it equal to zero by default and now we have both the shop order and customer entities so what about the relation between a shop order and the customer well when you think about it an order will always belong to only one customer if i go to the app which is already running on this device every order has only a single customer but as for the customer a single customer like this vern debert right here can have multiple orders so the relation is one customer too many orders and reversely many orders to one customer we're therefore going to use a 2 1 relation and a too many relation other kinds of relations are also possible within object box for them you should check out the official documentation of object box which is linked in the written tutorial so a shop order is going to have a relation to a final customer and this relation can be signified by writing 2 1 and then specifying the type so customer customer is the type of the entity that the shop order has a relation to so this is how you define a relation to one entity in this case customer and now the customer is related to many orders so we're going to create final orders and here we are going to say too many because a single customer can have many orders too many orders right too many shop order also we need to provide a add backlink annotation for this orders too many relation because this tells the entity that orders made by this particular customer will be gotten or backlinked or populated by looking at the 2 1 relation inside the shop order class these relations are going to allow us to easily get customers orders and also get the shop orders customer without needing to query the database ourselves for it this kind of related data is just going to be available to us easily now that we have the data model done we have the shop order and customer entity classes fully finished let's now go to home page dart and here we are first going to create a store in object box you access all of your data on a store instance but before we can access the data and write something to the store we first need to initialize that store object we're gonna do so from within init state so we'll want to store this store object inside a late store underscore store let's import store from object box dot dart and now let's edit this init state so as you can see right over here in united states we are already calling set new customer immediately when the app is initialized so that right when the app starts we're going to have a customer ready for whom we can begin to add orders and below this set new customer call we are now going to initialize this store so we are going to write store is equal to store and now this store accepts something called a model definition so where in the world are we going to get this model definition well this comes from the generated file so we do not need to worry about creating this model definition ourselves we just need to call get object box model which if we go to the location of this method which we are calling by hitting f12 we're gonna see that it indeed returns a model definition and it is inside the generated file and then what's also important is to specify the directory for the store so this directory will need to be the application documents directory that we can get from the path provider package find a package therefore we need to call get application documents directory this is the directory that can store persistent data it's not just going to get cleared for any reason and this returns a future directory so we would usually await this but since init state cannot be made asynchronous really what we are gonna do is instead of awaiting we are going to use the then continuation which is going to pass us a directory there and inside of this continuation let's make it into a blog body we're going to initialize the store from within this continuation right here and the directory can be gotten by joining the directory so there that path with slash sum name of the database file where we should store the database so let's just say object box actually even though we have not imported manually the path package which allows us to safely join two paths no matter the operating system we are running on because on some operating systems the ways of joining a path made it may be different than just a forward slash so even though we are not directly depending on path we can actually import package path slash pad dot dart and instead of doing this direct like an interpolated string we can instead say join right here so join and we want to join dot path with object box much better also whenever you initialize a store like this you should also close it so inside a dispose method we're going to call store dot close lastly because this is a late variable but this store is initialized only once this future has been successfully run for getting the application documents directory we need to have a way to find out if this store is already assigned because otherwise we are going to get the error of accessing late field before it's properly initialized sure we could make this store nullable and then check only if the store is not null in which case we would not access it but we do not want to introduce nullable fields to our app unless necessary so to mitigate this issue we can remain working with the late field but we also need to create a boolean has been initialized and set it equal to false by default and now whenever the store is initialized already we're going to say set state and set the has been initialized to true let's now take a look at how we can set the customers properly and add orders to the database so we are going to be able to set sort of the current customer for whom we are adding orders as you can see right here by pressing this button by which the name of the customer and the whole customer for whom we're adding orders changes and then we add orders for that new customer in this case it's kayla stam or stem i guess if you want to pronounce it like an american so we can do this and then change the customer and now the new customer is going to be angel flatly so it's kind of obvious that we are going to need to access this current customer object which is going to be of course of type customer entity right here we're gonna need to be able to access this object from the add a fake order for currentcustomer method so we need to keep this customer as a field inside our state class so let's do just that we are going to create a late customer underscore customer let's import customer entity over here from entities dart and we are already calling set new customer whenever the app is first initialized so that's good then we are also calling set new customer whenever we press this button but currently this set new customer method only prints out uh the name to the console so we want to change this we are going to instead say customer is set to a new value which is going to be a customer and we're going to populate the customer with a name from faker that person dot name again we do not populate the id that's the part that object box is going to do once we have this customer field inside of our state class we can add fake order for the current customer right this method is called from the other action on the add bar the one with the dollar icon so over here we're going to create an order first final order is equal to sharp order we need to set its price directly in the constructor so the price will come from this faker random generator integer between 10 and 500. cool and now we also need to set the customer for the order we only need to set the customer relation for the order because when you take a look at this the orders to many relation is actually back linked to the shop orders customer relation so as long as we set this customer to one customer relation on a shop order the other relation on the customer entity is going to be automatically handled so we only need to set a customer associated with the order that's it so how can we set that well we cannot just pass it to a constructor because uh we don't have any customer parameter in the shop or the constructor instead we need to access this customer field on a shop order object that's already created so let's say order dot customer and now we want to set this target for this relation so target and we're going to set it equal to the customer which is currently set as being the current customer in our state lastly this is where we are going to persistently put this shop order into the database and we can do that by saying store then each and every store has multiple boxes we are going to have one box per entity so since we are operating with the shop order entity we are going to access the shop order box and on this box we want to put the order object or the order entity and although we are only putting the order into database nowhere are we calling store box customer put still the customer is also going to be put into the database if it doesn't exist yet inside of that database so if we go here to our ios simulator and i create a new customer and now add the first order for that customer this customer malcolm kerlin is gonna be added automatically to the database just by calling store box shop order put then if i subsequently call add fake order for current customer more times like this this customer already exists in the database so it's not going to be edit there newly which is going to point to the already existing customer entity in the database from all of these new orders that we are adding there is more to relations and how the data is added and how you can update data within relations than i have just mentioned here and the documentation of object box is really awesome in this regard it explains everything very clearly and a link to this object box documentation about relations is available in the written tutorial but as for our app this kind of a basic knowledge about relations is completely enough so now we have the putting of the data into the database completely handled but it's of no use because even if i were to press these buttons and add orders and such we would still not see anything displayed in the ui because we are not displaying anything from the database so let's now handle that we're going to watch the data it's possible to perform a one-off read with object box but in a reactive framework like flutter it's almost always better to continuously watch the data using a stream and this stream is going to produce a new event whenever the data in the database is updated for example we're automatically going to receive the new orders when we press this add order button we're gonna need to rebuild the ui whenever a stream produces new events so we are going to wrap this order data table that should display that data inside a stream builder we can actually do so right now but before we do anything meaningful with this stream builder about which we're going to worry about later we need to first create a stream field in our state object so that's going to be a late stream that's going to hold a list of shop orders and let's call it underscore stream we are gonna want to start watching the database for the basic unsorted data right when the app starts so we're going to first set this stream directly from within init state and then later on we are also going to set this stream with some sorting enabled whenever this on sort method is run on the order data table but for now we are just going to worry about the non-sorted data just the basic data coming out of the database so inside init state as soon as we have initialized the store we are going to come into this set state method since we need to well set the state to rebuild the whole ui of this stateful widget and we are going to assign the stream to be equal to store dot box of shop order because we want to watch the shop orders after all shop order and then we want to query this shop order box and this is the simplest possible query we are not specifying any query conditions here but you can really do a lot with object box queries we could for example do something like query where shop order with an underscore at the end dot price dot is no or for example price is greater than 200 right we could do things like this but we're just going to quarry for all of the shop orders regardless of their price so we're going to keep this query this simple it's going to be empty and then we are going to say dot watch which is going to produce a stream of query sharp order and we also want to set trigger immediately to be true so that we get this data as soon as this watch method is called and not only when some sort of a new data is produced so trigger immediately is true all right and this stream is currently of type stream query shop order but we actually want to have a stream of list shop order so we need to actually transform these queries to an actual list of shop order data so we're going to map this query stream which passes us queries and we're going to say query dot find and this is going to produce the data we are after so now that everything is formatted you can see nicely that we are calling store box shop order then we call query with the simplest possible query for getting all of the data then we say watch which is going to produce a query object whenever the underlying data changes and then since we actually want to get the data we say query dot find now we can finally worry about displaying all of this data so the first step even before we mess with this stream builder is to actually be able to pass in the sharp orders into the order data table so how can we do that well we of course need to go into the order data table file and create a field on this widget that is going to be of type list shop order so let's create final list of sharp orders and let's call it orders let's add this as a required parameter to the constructor so this.orders and once we have it available in the widget we can finally go down to the data table and we are now going to touch columns because these just define the column names and the number of columns but we are only interested in these rows which is where the actual data is going to be displayed so we do not just want to hard code multiple data rows in here we actually want to produce these data rows the list of data rows right by mapping the list of orders so let me just cut out all of this this whole data road all right cut this out into your clipboard now we can remove this list literal and we are instead going to say widget dot orders which is the orders list and now we want to map each and every order of type shop order into a widget which is going to be that data row so let's return data row so let's just paste the content of the clipboard here boom and now of course since map returns iterable we need to call to list because rose needs a list non lazy list to be more precise so we're going to say that to list boom and lastly this should of course not contain the hard-coded things like hard-coded id in all caps string but instead it should display the actual id which we can get from the mapped order dot id and then convert that to string similarly for the customer name it's not going to be hard-coded customer name in all caps instead it's going to be gotten by calling order dot customer dot target because we want to get the target to which the relation points and then this is a nullable field so we need to access all of its data safely but still we can get the name of this customer and if it's null for some reason if this relation is not populated we're just going to handle it by displaying none but this is never going to actually happen in our app this relation is always going to be populated successfully as for the price we have this escaped dollar sign here so that's nice and then we also want to have interpolated order dot price and lastly we have this delete icon we're just going to leave it as it is for now we're going to handle the deletion later on so now we can worry about the stream builder in the home page because from it we are going to pass the actual list of shop orders into the order data table so this stream builder will work with a list of shop orders like this the stream is going to be the underscore stream which we are currently setting inside init state right here and even before this data from the stream arrives into this stream builder we first actually need to check if the store has been initialized and if it has not been initialized so not has been initialized instead of displaying this stream builder and the order data table we're going to display a center widget so let's say center if i provided the proper syntax for ternary operators so a question mark goes here and now centers child will be circular progress indicator so whenever we are still uh initializing the store so we have not yet gotten the application documents directory we're going to show a circular progress indicator like this otherwise if it is already initialized we can start showing a stream builder here with the order data table but even inside this stream builders builder method we need to check if not snapshot has data so if it hasn't got any data we're again going to show a center circular progress indicator so let's return that of course this is called duplication but for these kinds of simple example apps this is completely fine and well as for the order data table we need to pass in the orders which is going to be a list coming from the snapshot from the stream builder data and this data is nullable but since we have already checked that the snapshot must have data if we are displaying this orderdata table and numbers circular progress indicator we can just do a exclamation mark here to tell flutter and dart that we are assured the data is already here and that it's not null boom and just like that i have now saved the app hard reloaded it and we see this circular progress indicator in here if we take a look at the console maybe there's gonna be some error or actually not so that's cool of course there is currently no data coming through the stream because the database is completely empty i have not yet pressed any buttons so when i just create a new customer here and add an order for that customer nothing's really going to happen so let me just hard restart the app that usually solves it because we've been doing a lot of changes around here so how do we start that boom everything is now visible nicely that's good and we can now add a new order and it's immediately visible here so krista o'connor change the customer now the customer is really show walter these names are killing me really but everything is visible so now we can already display the data and add it to the database and this is the core stuff that you can do with object box but of course object box provides you with much much more functionality like proper querying of the data which we are actually not going to even do in this tutorial but what we are going to do is for example sorting the data because whenever we press this id column or this price column as you can see the arrow direction changes but we also want the sorting of the data to change according to the price or according to the id either ascendingly or descendingly so we already have this onsort callback on our order data table and if we take a look at its implementation right it's called whenever we press on the id column or on the price column we call on data column sort and here we simply set the local state of the or data table so that this arrow orientation changes basically and then we call this callback function passing it the column index which is pressed and then whether or not the sorting should be ascending or descending so we can use this column index integer and boolean ascending values from our homepage.dart to create a new ordered query on our database so let's do that since this query will be a bit more difficult than just this simple one here in uh set state in init state method we're going to separate it into multiple variables and we are not just going to write it all in line like this so let's just first create this kind of a query we can actually copy this bit so store box shop order query copy this and inside this callback function on sort in our order data table we're going to create final new query builder and set it equal to this copied value boom now in order to sort this query we are going to need to call new query builder dot order and this order takes in the property based on which we should order the data so this is actually gotten by calling shop order underscore which is the generated class sort of a companion class with our actual shop order entity and on this class we can access for example the id and now the data will be sorted based on this id or also price and now the data will be sorted based on this price this price is of type query integer property so you cannot just say shop order that price and pass in the actual integer here you need to pass in the shop order underscore that price which is not an integer but instead a query integer property so this is the generated class but we cannot just say shop order that price or shop order that id because we are going to sort based on a different property depending on the column index which is passed into this callback function so we're going to create a final sort field and set it equal to a different value based on the column index and if it is zero which means this id right here because this is zero index in our data table then we're gonna sort based on sharp order underscore dot id and if it is not zero it means that it must be two because this price is on the second index and this is the only other column based on which we can sort which we can press because for example we cannot press this customer column only id and price columns are pressable in our data table so we know that otherwise it's going to be sorted based on shop order dot price so shop or underscore that price right and now we can specify it here so new query builder that order based on sort field and also we need to specify whether we are going to be sorting ascendingly or descendingly so usually you would specify flags and if you leave it either unspecified like this or you say that the flags are zero you're going to sort ascendingly but we need to base this value upon the ascending boolean coming into this callback function so if ascending is true we're going to leave the flag to be zero if it's not true we're going to set it to order dot descending you can do very many things with this flags parameter on the order call you can combine multiple flags like order descending and then also or order dot case sensitive so you can really play around with your ordering or sorting of the values from the database but for us we can just keep it this simple link to the official documentation about ordering and all of its intricacies is in the written tutorial and once we have this query builder all set up we can again call set state and set the stream to a new stream which is going to be gotten by calling new query builder dot watch again and we want to trigger immediately set to be true much like in the init state method and then we're going to say map and we want to map individual queries to query that find again this is the same as in the init state method and so now what i can do is to tap on this price boom and now we are going to sort based on price as you can see all right and also based on the id ascendingly or also descendingly so this is amazing that we can do that this simply and it all just works because we are using reactive queries which object box provides now let's handle deleting the individual orders which is going to be very simple to do so much like we can put a new shop order into the database we can also remove it from there but for that we are going to need to be able to pass in the store into the order data table so let's go to order data table and just create simply a field final store store populate the constructor with it boom let's make it required and then right here after we import store from object box dot dart we can just scroll down into this last data cell which has this to do comment that we should delete the order from the database and all we need to do here is to just call widget dot store dot box and we're going to select the shop order box and it's as simple as calling remove and then we need to provide the entity id which we want to remove so we already have the shop order entity available based on which we are building this data row so we can just access order dot id and now after we go to the home page and pass in the store to the order data table so all the way down here let's say store is equal to underscore store now i can delete for example this second order the one with the id two by pressing here and it's deleted and now we have only orders one and three and of course i can add new ones for a new customer easily and then also delete them easy but if we have multiple orders for a customer it would be nice if we can just click this customer name and then show in that modal bottom sheet as you can see in the already finished app here to display all of the customers orders like this we already have all of the relations set up to be able to do this very easily all we need to do is to actually show and populate this bottom sheet right from the order data table data cell for the customer so whenever this data cell is tapped we want to show the customer's orders let's do that right now so i'm just going to show model bottom sheet we need to pass in the context and then a builder for the modal bottom sheet which is going to grant us a build context how else and now from this builder let's just return something very simple so we need to provide a background somehow white background so let's just return material and this material is going to wrap a trial which is going to be a list view and this is going to be a very simple list view with children specified on it directly and the children are going to come from older dot customer dot target so we have the order available which we are pressing right here so we need to get this orders customer first and then on this orders customer we can then access unsafely for now all of the orders so we are using all of the relations which we have set up we first use the relation to the customer on the order and once we have this customer already we then get all of the orders from this customer using the too many relation and this orders is really of type list although it's not really a list as you can see in the entities it's of course the type too many but when we take a look at too many by hitting f12 it is mixed in with the list mixing so it does behave like a list so therefore what we can do is to just call map on these orders so let's say orders.map and now we can map all of the orders let's just call it underscore for shortness so this underscore is the order which contains the customer id and price and let's just create a simple list style here that's going to contain a single title and this title will be of type oops type so will be of type text and this text is going to hold all of the data simply concatenated like an interpolated string so firstly it's going to be the order so underscore that id then let's put four spaces here then interpolate underscore.customer.target and then save access name and lastly again for spaces or something like that and put here interpolated price so underscore that price but since we want to show the dollar sign symbol before the price we're going to escape a dollar sign symbol before that interpolation boom and all we now need to do is call to list after this map call and that's it so now when we press on any kind of a customer we're going to see a modal bottom sheet displayed with all of the orders from that particular customer so henry so henry langos has these two orders curtis fisher has these four orders and so on rayleigh has these orders this code is sort of badly visible because it's just you know it's just cramped in here but if you want to get it and read it at your own pace you can always do so from the written tutorial now let's finally take a look at how easy it is to synchronize data between multiple devices because currently all of this data is just present on this single device or on the single emulator in our case but you can also use object box sync connect it sort of to your local data and then that object box sync is going to handle everything regarding synchronizing it on all of your different devices while the local database is completely free and open source from object box and it's always going to remain free and open source the object box sync is a paid product of object box and it's a really great way to keep your data synchronized across multiple different devices and it's a great alternative to things like firebase for example or some aws services because with object box it's absolutely simple to synchronize data you just basically run a single command do a little bit of configuration and your data is synchronizing just like that and also you are fully in control of your data you run object box sync on your own servers so that's also a huge plus so if you are interested in syncing your data definitely go to object box dot io forward slash sync link to that will also be in the video description and you can get a free trial of it and then also you see all of the different kinds of sync that are available and you can also just contact the object box team and they will set you up with the solution that you need to use sync you will need to have a sync server file i'm going to be running it on docker you probably don't have this file just yet unless you have contacted object box so unless you have it you are probably not going to follow along with this last part of the tutorial but it's still cool enough so that you should stick around so right here on my mac i have the sync server file here download it this file can be used with docker which i have running in the background already i have now restarted docker so that i can remove this image so that i can show you how to edit a new so once you have this file available it's completely easy to add it to docker so i'm just actually going to do it from command line let me open up a terminal here in this folder so i have sync server available right here and all i need to say is docker load input and then since we are in the same directory i'm going to say dot slash sync server.tar as easy as that and the image has been already loaded so when i go to docker we can see this image right here right and now of course you can be more elaborate about where the data is gonna get stored you can create a separate docker volume for the data but we are not going to worry about that in this showcase we are really just going to kick off this docker image and make it store the data directly inside of this flutter project so right inside of this vs code i'm going to open up terminal create a new window and i'm going to paste this command here all of this is also available inside of the documentation for object box which looks something like this so literally everything you need to know is inside of this documentation on the object box sync server so what is this command doing well it runs this image which we have just added to docker we are not using any authentication to secure our data but you have the option to use google authentication or you can also use a shared secret all of that is available in the documentation on how to do that and we are going to be running this on localhost port 9999 so once i run this it's not going to work because we need to most likely remove this this space that was added in here for some reason so let me do that boom easy and also what's important is that you are going to pass in the object box model.json file which is generated from your entities because this is what's being used by the object box sync server to actually sync all of your entities properly and for now all of the data will be stored simply in the data directory directly in our root of the flutter project but of course this is all configurable you obviously do not need to store your data in the root of your flutter project because this is only useful for development purposes obviously let's now actually delete all of the spacing after the forward slash or backslash right here all right so now this should work kind of all right so this is just something weird with formatting so i really i'm not sure why this is happening of course this will not run but let's now clear and paste the single line representation of the very same command but i just removed all of these slashes so now it's just a single line and now it should work actually boom and yes it is working so object box sync server started in 95 milliseconds it wasn't even painful just somehow the backslashes caused some trouble previously so now this is running and all we need to do now inside of our flutter app is to go to pubspeciamo and change the dependency object box flutter ellipse to object box sync flood ellipse save that the version is gonna remain the same now since we have just run flutter pubget we need to re-run our build runner so let's do that and let's just also include delete conflicting outputs for good measure and we can now go to our entities.dart file and we now need to mark them as being synchronized so we're going to mark it with add sync annotation the same goes for the customer entity so it's easy as that and now inside home page where we are initializing our store and everything like that once everything is generated it's just going to run properly again without errors here we go now we need to do just a little bit more setup we also need to have a late sync client field let's call it sync client with an underscore and now after we initialize the store we're just going to say if sync dot is available we of course need to import sync but we cannot do that for some reason but is available like that all right now it works then we also need to set the sync client equal to sync that client pass it the store basic the server uri and also credentials so let's first handle credentials since we have specified in the command which you can see right here that we are not going to use any credentials we use unsecured no authentication we are therefore going to pass sync credentials dot none here and as for the server uri i'm now running this on a localhost docker so i need to point to websockets so ws column slash and now it's going to be 127.0.0.1 and the port is 900 or 9999 like this because again this precise ip address is available right here so we are publishing it to one two seven zero zero one and then port is 9999 and then all we need to do is say sync client dot start and you can also do a bunch of more things on the same client like you can for example cancel updates and do all kinds of stuff but we are not really going to do that and also it's probably good to call syncline.close from the dispose method so let's do that sync client.close to release all of the resources now this ip address is completely fine and it's correct it's going to work for ios simulator but for android there is actually a special ip address when you try to point to localhost so if platform is android we're instead going to have here ws current slash slash 10.0.2.2 and the port is gonna remain the same so four nines and now it's gonna work also on android and on ios the same way i now need to stop running the app on my android emulator anyway because we have edit or changed a native dependency which is a plugin and in that case you always need to stop your app from running but also we have changed our entities to be synced but previously they were not synced if you do something like that you actually need to wipe your app's data if you already have an app in production not only in development and wiping the data is not an option whenever you change the previously non-synced entity to be synchronized there are ways to do it and everything is available in the documentation you can sort of migrate your data to another entity which is gonna be synced but in our case it's completely fine to just go ahead and go to object box tutorial hopefully it's this one nope go to object box tutorial and just go to storage and cache and clear storage boom and now i can run the app on android again so let's launch that and in the meantime i'm also going to call flutter dot run and select the ios simulator which is running also on my machine right here so i'm going to select the number 2 for iphone 12 pro and once everything will be running we're going to see the data synchronized between these two devices and all it took to synchronize this data is really just two commands and uh just a bit of setup client-side in us inside our flutter app but apart from that we didn't do really much and the data is just synchronized so that's awesome of course there is no data currently inside our android app because we have just wiped the data so uh we need to edit a new let's just wait for ios to also build here we go and now on android i can add a new order and boom it's also going to appear on ios similarly on ios i can add a new order and boom it's going to appear also inside our android device just like that it's super fast and super easy to implement i can also sort based on price sort based on ids and everything just works just as previously so that's completely awesome and this is it for this tutorial on object box you have seen how to build an app dealing with orders and customers and how to represent this data in the object box database you've learned about entities about relations about ordering the data about how to perform a reactive queries and you have probably also learned something about data table widget i guess at the end i've shown you how easy it is to synchronize your data across multiple different devices with object box sync so again if you are interested in sync this is a paid service which object box provides and be sure to contact object box and they are surely going to help you out with any kind of synchronization needs that you have inside of your app you're building but of course data synchronization is only an additional step that you can do with object box but it also works completely fine and completely for free as a local database package and it also shines in that regard because it's completely fast it has relation support so it's very nice to work with inside of your projects to go through this tutorial at your own pace once again and to get all of the code check out the written tutorial available from the link in the description and if you are serious about becoming a great floor developer who can build real apps for clients or at the job go to flutter.education link is also in the video description by the way to get the top curated flutter news and resources aimed at improving your app development career over there you can also subscribe to my mailing list to get the best flower resources delivered weekly right into your inbox and if you do not want to miss more tutorials like this be sure to subscribe to the channel and also join notification squad by hitting the bell button to make sure you grow your flutter skills because here on riso coder i am just determined to provide you with the best tutorials and resources so that you will become an in-demand flutter developer if this video helped you be sure to give it a like leave a comment if you have anything to say and see you in the next video [Music] you
Info
Channel: Reso Coder
Views: 15,106
Rating: undefined out of 5
Keywords: resocoder, tutorial, programming, code, programming tutorial, flutter, flutter tutorial, local database, flutter database, flutter objectbox, flutter local database, flutter database app
Id: AxYbdriXKI8
Channel Id: undefined
Length: 81min 47sec (4907 seconds)
Published: Tue May 18 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.