STUDY/Flutter

[플러터] FutureBuilder / StatelessWidget에서 데이터 패칭하기

ez1n 2024. 2. 28. 14:50

 

[Flutter_ FutureBuilder]

 

StatefulWidget을 사용하지 않고 api를 호출하여 데이터 패칭하는 방법을 알아보자.

 


 

플러터로 앱개발을 시작한 후 StatefulWidget으로 state를 정의하고 initState에서 데이터를 불러왔다..

(리액트의 useEffect와 유사하게 사용하고 있었다.)

그런데 플러터에서는 state를 잘 사용하지 않는다고 한다.

 

확실히 initState를 이용하는 경우 해당 데이터의 state를 모두 생성해 주어야하고,

데이터 패칭 함수를 호출한 뒤 state를 변경해야하기 때문에 상당히 번거롭다는 생각이 들긴했다.

((추가로 함수만 다르고 동일한 패턴의 코드가 screen마다 계속 발생하는 부분이 마음에 안들기도 했다(?)ㅋㅋ))

 

그런데 FutureBuilder라는 위젯을 사용하면 StatelessWidget에서 데이터 패칭, 로딩 상태 표현이 가능하다고 한다.

state를 생성하지 않고 비동기 함수를 호출해서 데이터를 받아올 수 있다..!

그래서 FutureBuilder에 대해 정리해 보려고 한다.

 


 

<STUDY>

 

 

FutureBuilder

비동기 데이터의 상태(로딩, 에러, 완료)에 따라 위젯을 보여줄 때 사용하는 위젯
  • future: 기다려야하는 데이터의 값 (비동기 데이터 전달)
  • builder: UI를 그려주는 함수
  • snapshot : future의 상태를 알 수 있음 (loading, error, done)

 

 

💡 전체 코드

 

  •  StatefulWidget 사용 (변경 전)
class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  List<DataModel> data = [];
  bool isLoading = true;

  @override
  void initState() {
    super.initState();
    fetchData();
  }

  void fetchData() async {
    var response  = await getData(); // 데이터 불러오기
    setState(() {
      data = response;
      isLoading = false;
    });
  }

  @override
  Widget build(BuildContext context) {
    if (isLoading) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
          
    return Container();
  }
}

 

- 데이터를 생성, 초기화한 이후 initState에서 업데이트한다.

 

  • FutureBuilder 사용 (변경 후)
class HomeScreen extends StatelessWidget {
  HomeScreen({super.key});

  final Future<List<DataModel>> data = getData(); 

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: data, // 비동기 데이터 전달
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Container()
          }
          return const Center(
            child: CircularProgressIndicator(),
          );
        },
      );
  }
}

 

 

💡 차이점

 

1️⃣ 데이터 정의

   - state를 정의하지 않고 바로 데이터 패칭 함수로 데이터를 불러온다.

   - 데이터 타입이 Future로 감싸져있다.

 

  • 변경 전
//...

  List<DataModel> data = [];
  bool isLoading = true;

  @override
  void initState() {
    super.initState();
    fetchData();
  }

  void fetchData() async {
    var response  = await getData(); // 데이터 불러오기
    setState(() {
      data = response;
      isLoading = false;
    });
  }
  
//...

 

  • 변경 후
//...

final Future<List<DataModel>> data = getData();

//...

 

 

2️⃣ 리턴할 위젯

   - FutureBuilder로 감싼 후 future와 builder를 구성한다.

   - isLoading이라는 state 대신 snapshot의 hasData를 이용하여 로딩 유무를 판별한다.

   - 오류가 발생하는 경우 snapshot의 hasError를 이용하여 에러 UI를 노출시킬 수 있다.

 

  • 변경 전
//...

  @override
  Widget build(BuildContext context) {
    if (isLoading) {
      return const Center(
        child: CircularProgressIndicator(),
      );
    }
          
    return Container();
  }
  
  //...

 

  • 변경 후
//...

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
        future: data, // 비동기 데이터 전달
        builder: (context, snapshot) {
          if (snapshot.hasData) {
            return Container()
          }
          return const Center(
            child: CircularProgressIndicator(),
          );
        },
      );
  }
  
  //...

 

FutureBuilder를 사용하니 확실히 코드가 더 간결해지는 것을 볼 수 있었다.

마음이 편-안해 지는 느낌☆

 

그리고 로딩 상태나 오류가 발생했을 때의 UI를 snapshot의 상태에 따라 (hasData, hasError 등) 표현할 수 있기 때문에

더욱 간편하게 느껴진다.

 


 

플러터를 공부하면서 숨은 기능들이 많다는 것을 계속 계속 느낀다.

js와는 또다른 매력이 있어 재밌게 배우고 있다.

열심히 공부해서 멋진 모바일 앱을 개발하고싶다 ㅎㅎ

 


 

 

🔆내가 보려고 정리하는 Flutter🔆

 

 

👉ez1n github 구경하기👈 

 

 

ez1n - Overview

Front-End Developer. ez1n has 14 repositories available. Follow their code on GitHub.

github.com