Flutter Future Widget Build

강정우·2023년 6월 7일
0

Flutter&Dart

목록 보기
52/87
post-thumbnail

Future Widget Build

  • Future Widget Build는 2개의 매개변수를 받고 그중 하나는 Http Req가 오면 해당 결과값을 주시하고 있다가 결과값에 변화가 생기면 자동으로 ui를 업데이트하는 기능을 갖고있다.
    이제 하나하나 자세히 알아보자..

1. http req

  • 우선 Future Widget Build와 연결하려면 위 Future 값을 반환하는 메서드를 바꿔줘야한다.
    반환타입을 Future<실제반환타입> 으로 말이다. the future resolves를 기반으로 해서

  • 따라서 최소 2개의 키 parameter가 필요한데 우선

  1. future : 여기가 바로 future에 listen하는 값이다.
  2. builder : funtion the excute when future produce the data
    • 그리고 여기에는 context : 그동안 작성해온 context 현재 위젯에 해당하는 메타정보를 담고있다.
      snapshot : future의 state에 대한 값의 정보를 답고있다.
      참고로 위 두개의 매개변수는 첫번째 파라미터인 future에 의해 자동적으로 담긴다.
  • 또한 Future builder는 에러 핸들링은 다르게 한다. 굉장히 짧은 코드만을 이용한다

  • 뭐 loading state도 필요없고~

  void _loadItems() async {
    final url = Uri.https(
      'react-http-e4fe2-default-rtdb.asia-southeast1.firebasedatabase.app',
      'shopping-list.json',
    );
    try {
      final response = await http.get(url);
      // throw Exception('An error occurred!');
      if (response.body == 'null') {
        setState(() {
          _isLoading = false;
        });
        return;
      }

      if (response.statusCode >= 400) {
        setState(() {
          _error = "Failed to fetch data. Plz try again later.";
        });
      }

      final Map<String, dynamic> listData = json.decode(response.body);
      final List<GroceryItem> loadedItems = [];
      for (final item in listData.entries) {
        final tempCategory = categories.entries
            .firstWhere((data) => data.value.title == item.value['category'])
            .value;
        loadedItems.add(GroceryItem(
            id: item.key,
            name: item.value['name'],
            quantity: item.value['quantity'],
            category: tempCategory));
      }
      setState(() {
        _groceryItems = loadedItems;
        _isLoading = false;
      });
    } catch (err) {
      setState(() {
        _error = err.toString();
      });
    }
  }
  Future<List<GroceryItem>> _loadItems() async {
    final url = Uri.https(
      'react-http-e4fe2-default-rtdb.asia-southeast1.firebasedatabase.app',
      'shopping-list.json',
    );
    final response = await http.get(url);
    // throw Exception('An error occurred!');
    if (response.body == 'null') {
      return [];
    }

    if (response.statusCode >= 400) {
      throw Exception('Failed to fetch grocery items. Please try again later.');
    }

    final Map<String, dynamic> listData = json.decode(response.body);
    final List<GroceryItem> loadedItems = [];
    for (final item in listData.entries) {
      final tempCategory = categories.entries
          .firstWhere((data) => data.value.title == item.value['category'])
          .value;
      loadedItems.add(GroceryItem(
          id: item.key,
          name: item.value['name'],
          quantity: item.value['quantity'],
          category: tempCategory));
    }
    return loadedItems;
  }
  • 위 함수처럼 코드를 매우 짧게 줄일 수 있다. 하지만 return 값이 future라고 아래 코드처럼 사용하는 것은 절대 권장되지 않는다. 왜? => 함수를 그냥 집어넣으면 builder 메서드가 재실행될때마다 즉, state가 바뀔 때 마다 계속 http req가 실행될꺼 아니야?! 이는 존나 비싼 작업이 된다.

late 키워드

  • nonenullable value 즉, null일 수 없는 값에 대하여 부여하는 키워드이다.

  • 이는 앞서도 설명한 적이 있다. 이 키워드는 초반에는 물론 값이 안 들어있지만 해당 값이 사용되기 전에는 반드시 값이 있다는 것을 알려줄 때 사용되는 키워드이다.

  • 즉, 여기 future에서 해당 값에 대하여 listen하고 있다가 값이 바뀌면 builder 메서드를 실행하는 것이다.
    그리고 이제 builder 메서드에서 값을 반환하는데 이때 한개의 위젯을 반환하는 것이 아닌 다양한 위젯을 반환해도 된다.

  • 데이터만 로드해야 하는 화면이나 위젯이 있다면 로드 완료 여부에 따라
    다른 상태를 보여주고 데이터와 관련된 다른 논리가 없다면요
    미래의 건축가가 이상적이겠죠

  • 현재 상태에 기반해 다양한 상태를 렌더링하는 과정을 단순화할 수 있으니까요

profile
智(지)! 德(덕)! 體(체)!

0개의 댓글