Flutter - Future/FutureBuilder - 비동기 프로그래밍 개념, 사용 방법, 예시(async, await, then)

반응형

 

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 클래스를 다루기 쉽게 해줌

기본 요소

  1. Future
    • 비동기 작업을 나타내는 객체
  2. Builder
    • 데이터가 활용될 때 실행되는 함수
    • AsyncSnapshot 객체를 사용하여 UI 빌드
    • AsyncSnapshot : Future에서 반환된 데이터를 포함하는 객체
    • AsyncSnapshot에 반환된 값은 data 속성에 저장
  3. 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

 

반응형