Deepening Flutter asynchronous tasks
Entering
Synchronous means that all tasks are processed sequentially, while asynchronous means that tasks are processed in parallel. That is, it starts the next task without waiting for the completion of the previously started task.
Comparing synchronous and asynchronous in code
Synchronous code
After all tasks 1 are completed, task 2 will start and the message ‘All tasks completed’ will be displayed.
void main() {
print('작업 1 시작');
task1();
print('작업 2 시작');
task2();
print('모든 작업 완료');
}
void task1() {
for (int i = 0; i < 1000000000; i++) {}
print('작업 1 완료');
}
void task2() {
print('작업 2 완료');
}
// result
작업 1 시작
작업 1 완료
작업 2 시작
작업 2 완료
모든 작업 완료
Asynchronous code
The following code is based on an asynchronous method, and as a result, you can see that the task is processed according to duration. This means that there is a mismatch in the order of code operations within wait.
void main() async {
print('작업 시작');
await Future.wait([
task1(),
task2(),
task3()
]);
print('모든 작업 완료');
}
Future<void> task1() async {
await Future.delayed(Duration(seconds: 2));
print('작업 1 완료');
}
Future<void> task2() async {
await Future.delayed(Duration(seconds: 1));
print('작업 2 완료');
}
Future<void> task3() async {
await Future.delayed(Duration(seconds: 3));
print('작업 3 완료');
}
// result
작업 시작
작업 2 완료
작업 1 완료
작업 3 완료
모든 작업 완료
Deepening Flutter asynchronous tasks
State management and asynchrony
As in the code presented above, an example is to delay until the result of an asynchronous operation is obtained and then reflect it in the setState state. This applies even if the operation starts asynchronously, but the resulting processing must appear synchronous to the user.
- You can see asynchronous processing using
asyncandawait. Addasyncto create an asynchronous function, andawaitwaits forFutureto complete and returns the result when complete. Futureis an object that represents the result of an asynchronous operation and provides results or errors after the operation is completed.- You can prevent duplicate requests by processing whether the button is activated or not (
setState) before and after returningFuture.
Future<void> resetGameTiles(int tile1, int tile2) async {
await Future.delayed(Duration(milliseconds: 1500));
setState(() {
tileStates[tile1] = false;
tileStates[tile2] = false;
});
selectedTile = -1;
}
Future chaining method
In addition to the above methods, Future provides a Future chaining method for asynchronous operations.
Future.then(),Future.catchError(),Future.whenComplete()task1().then((value) => task2()).catchError((e) => print(e));- You can execute
task2according to the value oftask1, and in the process, you can simply express tasks such as catching errors and outputting logs.
Difference between Future and Stream
Future returns data only once, and Stream is used for continuous stream processing, that is, returning multiple data asynchronously, like other languages. You can consider asynchronous state management using the StreamBuilder widget for real-time data processing.
Completer class
There is a way to complete a Future externally using Completer. An object that can control asynchronous operations and returns a Future object with completer.complete.
Future<String> fetchData() {
Completer<String> completer = Completer<String>();
Future.delayed(Duration(seconds: 2), () {
completer.complete('데이터 로드 완료');
});
return completer.future;
}
Why use Completer? Advanced control for asynchronous operations is available right away. This is because you can manually control the return completion point of Future, which is automatically completed as shown in the code.
- Because it contains a
Futureobject insideCompleter
UI and FutureBuilder
FutureBuilder tracks the state through snapshots until Future completes. You can control completion and error states depending on the snapshot.connectionState state. During loading, CircularProgressIndicator is displayed and the result is returned after loading.
- You can provide a message for error handling with
snapshot.hasError.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('비동기 작업 예시')),
body: Center(
child: FutureBuilder<String>(
future: fetchData(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator(); // 로딩 중일 때 인디케이터
} else if (snapshot.hasError) {
return Text('에러 발생: ${snapshot.error}');
} else if (snapshot.hasData) {
return Text('결과: ${snapshot.data}');
} else {
return Text('데이터 없음');
}
},
),
),
);
}
Comments
No comments yet. Be the first!