I have a flutter application where I am using the SQFLITE plugin to fetch data from SQLite DB. Here I am facing a weird problem. As per my understanding, we use either asyn
Adding to the above answers.
Flutter Application is said to be a step by step execution of code, but it's not like that. There are a lot of events going to be triggered in the lifecycle of applications like Click Event, Timers, and all. There must be some code that should be running in the background thread.
How background work execute:
So there are two Queues
Microtask Queue
runs the code which not supposed to be run by any event(click, timer, etc). It can contain both sync and async work.
Event Queue
runs when any external click event occurs in the application like Click event, then that block execution done inside the event loop.
The below diagram will explain in detail how execution will proceed.
Note: At any given point of application development Microtask queue will run then only Event Queue will be able to run.
Working with futures: async, await, then and Future
The async
and await
keywords provide a declarative way to define asynchronous functions and use their results. Remember these two basic guidelines when using async
and await
:
async
before the function body:await
keyword works only in async
functions.Here’s an example that converts main()
from a synchronous to asynchronous function.
First, add the async
keyword before the function body:
void main() async { ··· }
If the function has a declared return type, then update the type to be Future<T>
, where T is the type of the value that the function returns. If the function doesn’t explicitly return a value, then the return type is Future<void>
:
Future<void> main() async { ··· }
Now that you have an async
function, you can use the await
keyword to wait for a future to complete:
print(await createOrderMessage());
.Then((value){…})
is a callback that’s called when future
completes successfully(with a value).
await createOrderMessage().then((value) {...});
Full Example of async, await, then and Future
Future<String> createOrderMessage() async {
var order = await fetchUserOrder();
return 'Your order is: $order';
}
Future<String> fetchUserOrder() =>
// Imagine that this function is
// more complex and slow.
Future.delayed(
Duration(seconds: 2),
() => 'Large Latte',
);
Future<void> main() async {
print('Fetching user order...');
print(await createOrderMessage().then((value) {
print(value);
return value;
}));
}
in simple words:
await
is meant to interrupt the process flow until the async method has finished.
then
however does not interrupt the process flow (meaning the next instructions will be executed) but enables you to run code when the async method is finished.
In your example, you cannot achieve what you want when you use then
because the code is not 'waiting' and the return
statement is processed and thus returns an empty list.
When you add the await
, you explicitey say: 'don't go further until my Future
is completed (the then
part).
You could write your code as follow to achieve the same result only with await
:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
List<Map<String,dynamic>> expList = await db.query(expTable,where: '$expTable.$expFundId = $fundId');
expList.forEach((Map<String, dynamic> expMap) {
expenseList.add(Expense.fromMap(expMap));
});
return expenseList;
}
You could also chose to use only the then
part, but you need to ensure to call getExpensesByFundId
properly afterward:
Future<List<Expense>> getExpensesByFundId(int fundId) async {
Database db = await database;
List<Expense> expenseList = List();
return db.query(expTable,where: '$expTable.$expFundId = $fundId')
.then((List<Map<String,dynamic>> expList){
expList.forEach((Map<String, dynamic> expMap){
expenseList.add(Expense.fromMap(expMap));
});
});
}
// call either with an await
List<Expense> list = await getExpensesByFundId(1);
// or with a then (knowing that this will not interrupt the process flow and process the next instruction
getExpensesByFundId(1).then((List<Expense> l) { /*...*/ });
When making class use async
for using await
its simple logic to make a wait state in your function until your data is retrieve to show.
Example: 1) Its like when you follow click button 2) Data first store in database than Future
function use to retrieve data 3) Move that data into variable and than show in screen 4) Variable show like increment in your following/profile.
And then
is use one by one step of code, store data in variable and then move to next.
Example: If I click in follow button until data store in variable it continuously retrieve some data to store and not allow next function to run, and if one task is complete than move to another.
Same as your question i was also doing experiment in social media flutter app and this is my understanding. I hope this would help.