Develop/Flutter

[Flutter] 플러터 FutureBuilder를 사용한 비동기 처리

JunJangE 2021. 11. 16. 23:22

이전에 Dart 문법에 대해서 알아보면서 비동기 처리에 대해서 다뤄보았다.  

이번에는 이전에 다뤘던 비동기 처리의 개념 중 자주 사용되는 FutureBuilder에 대해서 알아보자.

 

[Flutter] 플러터 Dart(다트) 문법 정리

이번에는 플러터에서 사용되는 Dart 문법에 대해서 알아보자. DartPad dartpad.dev Dart 언어만을 다루기 때문에 위 링크를 통해 Dart 문법에 대해서만 확인하면서 진행하도록 하자. var와 dynamic Dart에서 Ja

fre2-dom.tistory.com

비동기 처리에 대해서 잘 모른다면 위 링크를 통해 한번 읽어보고 오면 이해하기 더 좋을 것 같다.

FutureBuilder는 Future를 사용하는 이유와 같이 데이터를 모두 다 받기 전에 먼저 데이터가 없이 그릴 수 없는 부분을 먼저 그려주기 위해 사용이 되는 것이다. 만약 FutureBuilder가 없다면 데이터가 다 받아지기를 기다린 후 화면을 그리거나 데이터의 변함을 setState()를 통해 바꿔야 줘야 할 것이다.

FutureBuilder는 대부분 앨범에서 이미지 가져오기, 현재 배터리 표시, 파일 가져오기, http 요청 등 일회성 응답에 사용한다.

Flutter 공식 사이트에 있는 FutureBuilder 문서에 있는 코드를 조금 수정했는데, 코드를 확인하면서 알아보자.

코드

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

// 비동기 처리를 할 때 화면을 동적으로 변화시키기 위해 StatefulWidget를 사용
class MyHomePage extends StatefulWidget {

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Flutter Study"),
        centerTitle: true,
        elevation: 0.0,
      ),
      
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              '데이터를 불러오는 중입니다.',
              style: TextStyle(fontSize: 20),
            ),

            SizedBox(
              height: 20.0,
            ),

            // FutureBuilder 예시 코드
            FutureBuilder(
                future: _future(),
                builder: (BuildContext context, AsyncSnapshot snapshot) {

                  //해당 부분은 data를 아직 받아 오지 못했을 때 실행되는 부분
                  if (snapshot.hasData == false) {
                    return CircularProgressIndicator(); // CircularProgressIndicator : 로딩 에니메이션
                  }

                  //error가 발생하게 될 경우 반환하게 되는 부분
                  else if (snapshot.hasError) {
                    return Padding(
                      padding: const EdgeInsets.all(8.0),
                      
                      child: Text(
                        'Error: ${snapshot.error}', // 에러명을 텍스트에 뿌려줌
                        style: TextStyle(fontSize: 15),
                      ),
                    );
                  }

                  // 데이터를 정상적으로 받아오게 되면 다음 부분을 실행하게 되는 부분
                  else {
                    return Padding(
                      padding: const EdgeInsets.all(8.0),

                      child: Text(
                        snapshot.data.toString(), // 비동기 처리를 통해 받은 데이터를 텍스트에 뿌려줌
                        style: TextStyle(fontSize: 15),
                      ),
                    );
                  }
                })
          ],
        ),
      ),
    );
  }

  // 비동기 처리
  Future _future() async {
    await Future.delayed(Duration(seconds: 5)); // 5초를 강제적으로 딜레이 시킨다.
    return '짜잔!'; // 5초 후 '짜잔!' 리턴
  }
}

코드의 흐름을 확인해보면 FutureBuilder 메소드를 통해 비동기 처리 함수를 불러오게 되는 것을 확인할 수 있고 처음 5초가 지나기 전까지는 data를 받아 오지 못했으므로 snapshot.data가 false 가 되어 로딩 애니메이션이 나오게 된다. 5초 후에는 '짜잔!' 이라는 data를 받게 되어 Text에 받은 data를 뿌려주게 된다.

코드를 실행시켜보면 다음 실행 화면과 같이 나오는 것을 확인할 수 있다.

<실행 화면>

참고

 

FutureBuilder class - widgets library - Dart API

Widget that builds itself based on the latest snapshot of interaction with a Future. The future must have been obtained earlier, e.g. during State.initState, State.didUpdateWidget, or State.didChangeDependencies. It must not be created during the State.bui

api.flutter.dev