반응형
Future 란?
- 비동기 계산의 결과를 나타내는 클래스
- 값을 반환할 때 즉시 결과를 계산하는 동기 계산과 달리 비동기 계산은 즉시 결과를 제공할 수 없음
- 비동기 계산은 시간이 걸리는 프로그램 외부의 작업을 기다려야 할 수 있음
- 파일 읽기, 데이터베이스 쿼리, 웹 페이지 가져오기 등
- 비동기 계산 결과를 사용할 수 있을 때 결과로 Future 타입의 '완료' 값을 반환
Future를 이해하기 위한 비동기 프로그래밍의 개념
C# 언어로 작성된 비동기 프로그래밍 코드와 개념, 절차를 설명한 포스팅이 있습니다.
비동기 프로그래밍의 개념은 어느 언어에서와 비슷하므로 이해가 어렵다면,
아래의 포스팅을 한 번 봐보시는 것을 추천드립니다.
비동기식 프로그래밍이란?
- 나열된 작업을 직렬이 아닌 병렬식으로 동시에 처리하는 것
- 즉, 동시에 처리하기 때문에 특정 작업을 수행하기 위한 대기시간이 필요하지 않고 빠르게 처리가 가능함
Flutter에서의 비동기 프로그래밍
- async 키워드를 이용하여 비동기 계산을 수행하는 함수를 사용
- 비동기 함수 내에서 await 키워드를 사용하여 비동기 계산 결과가 나올 때까지 실행 지연
- await 키워드로 함수의 실행이 지연되는 동안 프로그램은 멈추지 않고 다른 작업을 계속 수행
- 작업의 결과를 얻기 위해서는 Future 클래스의 then 메서드나 await 키워드를 사용하여 대기
- 예시) 2초 뒤에 '123' 이라는 정수의 값을 반환하는 비동기 함수
// async, await 키워드 사용
// 비동기 함수 선언하고 값 반환하기
Future<int> getNumber() async {
await Future.delayed(Duration(seconds: 2));
return 123;
}
// then 메서드 사용
// 비동기 함수 호출하고 값 출력하기
getNumber().then((result) {
print('Result: $result'); // 2초 뒤 Result: 123 출력
});
Future의 상태 값(State)
- Future.waiting
- 비동기 작업이 아직 완료되지 않은 상태
- 즉, 비동기 계산을 대기하는 상태
- Future.done
- 비동기 작업이 완료된 상태
- 즉, 결과를 정상적으로 얻은 상태를 의미
- Future.error
- 비동기 작업 중 에러가 발생한 상태
FutureBuilder 란?
- 비동기 작업 결과를 효과적으로 표시하기 위해 사용되는 위젯
- 비동기 작업을 결과를 사용하여 UI를 빌드하는 데 사용
- 데이터베이스 쿼리, API 호출 등 다른 네트워크 요청과 같은 비동기 작업의 결과
- Future 객체와 결과를 처리하는 콜백함수를 받아들임
- 즉, Future 클래스를 다루기 쉽게 해줌
기본 요소
- Future
- 비동기 작업을 나타내는 객체
- Builder
- 데이터가 활용될 때 실행되는 함수
- AsyncSnapshot 객체를 사용하여 UI 빌드
- AsyncSnapshot : Future에서 반환된 데이터를 포함하는 객체
- AsyncSnapshot에 반환된 값은 data 속성에 저장
- InitialData
- 비동기 작업이 완료되지 않았을 때 Future 객체가 값을 반환할 때까지 표시될 초기 데이터
FutureBuilder의 상태 값(State)
- ConnectionState.waiting
- 비동기 작업이 진행 중인 상태
- ConnectionState.done
- 비동기 작업이 완료된 상태, 반환된 결과 데이터 사용 가능
- ConnectionState.none (혹은 ConnectionState.active)
- 초기 데이터가 있지만, 비동기 작업이 아직 완료되지 않은 상태
* Future 객체의 상태가 변경됨에 따라 FutureBuilder를 사용하여 UI를 동적으로 업데이트 할 수 있음
상태값을 이용하여 비동기 작업하기
코드
- 예시) 앱 실행 시 2초간 대기하고 출력 결과 표시하기
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: 'Flutter Code Sample',
home: MyStatefulWidget(),
);
}
}
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
// 2초 뒤 'Data Loaded' 의 값 반환
final Future<String> _calculation = Future<String>.delayed(
const Duration(seconds: 2),
() => 'Data Loaded',
);
@override
Widget build(BuildContext context) {
return FutureBuilder<String>(
// 비동기 작업을 할 객체의 값
future: _calculation,
builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
// 비동기 작업이 완료될 경우
if (snapshot.connectionState == ConnectionState.done) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Icon(
Icons.check_circle_outline,
color: Colors.green,
size: 60,
),
Text('Result: ${snapshot.data}'),
],
),
);
}
// 비동기 작업이 완료되지 않을 경우
else {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 60,
height: 60,
child: CircularProgressIndicator(),
),
Text('Awaiting result...'),
],
),
);
}
},
);
}
}
실행
- 실행 후 2초 뒤 'Data Load' 문구 출력
참고
flutter - dart:async - Future<T> abstract class
flutter - widgets - FutureBuilder<T> class
flutter - widgets - StreamBuilder<T> class
반응형