Heavy operation flutter sqlite background - flutter

I ask you a quwstion because i Need to develop an application with background synchronization. I tried to look around but i didn't find something usefull. My requirement Is to do background fetch of datas from apis and save them to database. One sunchronization can be heavy(12k inserits). It this process block UI?
The user could continue to use app while synchronizing.
Thank you

For heavy read/write, you can use https://pub.dev/packages/hive instead of sqlite
Hive have better performance than sqlite

You need to use a dedicated isolate to perform heavy calculations, for that you can use compute
final data = await compute(callback, arguments);
Documentation:
https://api.flutter.dev/flutter/foundation/compute.html
Example:
Flutter- compute method

Related

Is it recommended to use Stream Builder for a single data fetched from a database? if so, will it highly affect the performance of my app?

Is there any problem using StreamBuilder for a single set of data that is fetched from database in my app?
Stream builder is to continuously get data. Even if its a single data or multiple entries if the app needs to fetch data continuously then its good to use Stream builder. Btw fetching single entry will not affect the performance of the app to a great extent. So you should be good to go with Stream builder
https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html
In general terms, no, it is not a problem nor does it greatly effect the performance of the app.
But as always, it depends on more factors. Let for instance say you have a ListView with a bunch of Card in it. And in each Card you have 10 Text-widgets. If you now have a StreamBuilder for each of those Text-widget, and each StreamBuilder does separate requests to your database, and each query is timeconsuming... then yes; it is not optimal. But if it in the end will effect the performance is still hard to say. You'd have to test :) Don't optimize before you need to.

Should I use ObjectBox in a separate isolate so as not to block UI thread?

I'm going to use ObjectBox in my Flutter project. But I noticed that the get method is synchronous. So should I use ObjectBox in a separate isolate to avoid blocking the UI thread?
There's rarely a need to do so. ObjectBox achieves hundreds of thousands of read objects per second on mobile so you should be fine unless you're doing something very excessive.
objectbox-dart v1.4.0 adds Store.runIsolated to run database operations (asynchronous) in the background.
https://github.com/objectbox/objectbox-dart/releases/tag/v1.4.0

ObjectBox Dart/Flutter multi-isolate access

Creating a separate thread for a question stated in a comment...
How does ObjectBox handle concurrent(by different threads/isolates) write requests? example of my use case: FCM "onBackgroundmessage" call runs in a different isolate, the same time multiple write requests might happen. "Hive" is failing in this case completely. Is there any inbuild solution in ObjectBox?
ObjectBox for dart is based on a native ObjectBox core library that handles concurrency using Transactions. Let me pick out few points relevant to the question:
Transactions manage multi-threading; e.g. a transaction is tied to a thread and vice versa.
Read(-only) transactions never get blocked or block a write transaction.
There can only be a single write transaction at any time; they run strictly one after the other (sequential).
As for the isolates in Dart/Flutter - yes, they can safely access the same store, you just need to make sure it really is the same native store instance. To do so, you do the following steps:
Create a Store() instance in your main isolate, as you normally would.
Get ByteData store.reference which contains the information about the native store.
Send this reference to another isolate, via a SendPort.
In another isolate, receive the reference and open a local Store instance, using Store.fromReference(getObjectBoxModel(), msg as ByteData).
Now both isolates have their own Dart Store instances which internally use the same underlying native store. Therefore, their transactions are synchronized, they both see the same data and get notifications on data changes. 🎉
You can see the code I've just described this test case: https://github.com/objectbox/objectbox-dart/blob/461a948439dcc42f3956b7d21b232eb9c2bc26e1/objectbox/test/isolates_test.dart#L50
Make sure you don't close the store while another isolate is still using it. Better not close it at all - that's best practice in normal applications without huge amounts of background work.

Why it must be use the await for save/get local data in Flutter?

I want to save data to local(just a few data), and I find several package for do that (e.g shared_preferences,secure_storage,sqflite), but all of them are need to use await (Future), if I use these, I have to change my existing codes for wrap in Future, but I just feel that's very troublesome, so I am wondering why all of these are need to use await for save data? or can I use another easy way to do that?
Thanks!
To be clear: It is impossible to have a synchronous system call in flutter.
This is due to an architectural decision: Instead of having the language bridge, Flutter uses two bus (one dart, one native) sending messages to each other.
This is faster than by using a bridge but enforce asynchronous messages.
await as the name suggest wait for some event without stopping following lines of code to execute because that work will take some milliseconds to perform. So, it's a good idea to use await which needs to have async in the function.
There is other way of doing this work without using async-await.
That's then().
So, you go with this without having to add async to your function.
performWork().then((result) {}));
If you do not wish to use await you can call then() on the Future object. Refer this link for more details.
If you are working with Flutter you will definitely have to handle Future's there is no work around it.

What's the proper way to use sqlite on the iPhone?

Can you please give some suggestions on sqlite using on the iPhone?
Within my application, I use a sqlite DB to store all local data. Two methods can be used to retrieve those data during running time.
1, Load all the data into memory at initialization stage. (More memory used, less DB open/close operation needed)
2, Read corresponding records when necessary, free the occupied memory after using. (Good habit for memory using, but much DB open/close operations needs).
I prefer to use method 2, but not sure whether too many DB opening/closing operations could affect app's efficiency. Or do you think I can 'upgrade' method 2 by opening DB when app launches and closing DB when app quits?
Thanks for your suggestions very much!
First of all: use FMDB to access SQLite!
Then, create your own singleton "MyDB" class.
Every time you need the database, you do [MyDB instance] to get your FMDB instance.
That way you only have one DB open (in didFinishLaunching) an you close it when your app exits.
That's far and away the best way to use SQLite on the iPhone.
The other option is to use CoreData, something I find great for when you start with an empty database, but FMDB/SQLite works best for me if I have a set of data that's read-only.
Apple seems to suggest that you avoid preloading all the data during the startup in order to ensure faster and smoother startup. Supposedly you should only load data when/if the user needs it.