Flutter: avoid UI freeze when massive Database operation is in progress
The problem is that Flutter is Single Threaded, so once you get a heavy process running, your Single Thread will block anything else.
The solution is to be smart on how to use that Single Thread.
Dart will have an Event Queue with a bunch of Futures
waiting to be processed. Once the Dart engine sees an await
it will let another Future
grab hold of the Single Thread and let it run. This way, one Future
will run at a time inside an Isolate
.
So if we get smart about it, we let everyone play at it's own time, in other words, we break down our tasks into smaller tasks, so the Dart engine won't starve other Futures
, and all the processes awaiting for running can have their time.
The equivalent for your code would be something like this (assuming the for
is what takes lots of time to execute, because of a large collection, and not it's individual steps):
static Future<void> _parseResponse(xml.XmlElement elements) async {
Database db = await MyDatabaseHelper.openConnection();
db.transaction((tx) async {
Batch batch = tx.batch();
for (xml.XmlElement oi in elements.children) {
await Future(() {
int id = int.parse(oi.findElements("ID").first.text);
String name = oi.findElements("NAME").first.text;
DatabaseHelper.insertElement(
tx,
id: id,
name: name,
);
);
}
batch.commit(noResult: true);
});
}
This will fragment each step of your for
loop into a Future
, so at each step your UI will have the opportunity to execute whatever it needs to execute to keep your animations smooth. Keep in mind though that this will have the side effect of slowing down _parseResponse
as putting each for
step into the Future
Event Queue will have an additional cost, so you might want to optimize this further for your particular use case.