티스토리 뷰

반응형

[1] 문서보기 

 

FutureBuilder 는 Future와 상호작용한 마지막 스냅샷으로 자신을 빌드하는 위젯(?) 이라고 합니다. 

 

 

정의가 잘 안와닿는데, 

사용용도를 보면 확 이해가 됩니다 

 

API콜을 해서 응답을 받기 전까지는 로딩 위젯를 보여주고

성공 응답을 받으면 데이터를 보여주는 위젯을 보여주고

실패 응답을 받으면 에러메세지를 보여주는 위젯을 보여주고 

싶을때 쓰는 위젯입니다. 

 

 

문서에 예제가 너무 잘되어있는데 이런식으로 쓸 수 있습니다. (문서코드 복붙)

class MyStatefulWidget extends StatefulWidget {
  MyStatefulWidget({Key key}) : super(key: key);

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

/// This is the private State class that goes with MyStatefulWidget.
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  Future<String> _calculation = Future<String>.delayed(
    Duration(seconds: 2),
    () => 'Data Loaded',
  );

  Widget build(BuildContext context) {
    return DefaultTextStyle(
      style: Theme.of(context).textTheme.headline2,
      textAlign: TextAlign.center,
      child: FutureBuilder<String>(
        future: _calculation, // a previously-obtained Future<String> or null
        builder: (BuildContext context, AsyncSnapshot<String> snapshot) {
          List<Widget> children;
          if (snapshot.hasData) {
            children = <Widget>[
              Icon(
                Icons.check_circle_outline,
                color: Colors.green,
                size: 60,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Result: ${snapshot.data}'),
              )
            ];
          } else if (snapshot.hasError) {
            children = <Widget>[
              Icon(
                Icons.error_outline,
                color: Colors.red,
                size: 60,
              ),
              Padding(
                padding: const EdgeInsets.only(top: 16),
                child: Text('Error: ${snapshot.error}'),
              )
            ];
          } else {
            children = <Widget>[
              SizedBox(
                child: CircularProgressIndicator(),
                width: 60,
                height: 60,
              ),
              const Padding(
                padding: EdgeInsets.only(top: 16),
                child: Text('Awaiting result...'),
              )
            ];
          }
          return Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              crossAxisAlignment: CrossAxisAlignment.center,
              children: children,
            ),
          );
        },
      ),
    );
  }
}

 

 

참고로 FutureBuilder는 StatefulWidget의 자식클래스이고 

 

 

생성자는 이렇게 생겼습니다. 

 

https://api.flutter.dev/flutter/widgets/FutureBuilder/FutureBuilder.html

 

 

[2] 실전예제

오늘의 질문을 api콜해서 받아와서 보여주는 HomeWidget을 FutureBuilder를 통해 만들어보겠습니다.

 

우선 Question 모델, Question 서비스가 이렇게 있습니다. 

(json["detail"]의 값은 에러 메세지 입니다. )

 

 

 

HomeViewModel을 만들어주고 

 

 

HomeWidget도 간단버전으로 구현해줍니다. 

 

 

데이터가 있을때는 snapshot.data를 이용해서 화면을 그려주고

에러일때는 snapshot.error를 이용해서 화면을 그려주면 되겠네요.

 

그리고 로딩중일때는 CupertinoActivityIndicator를 보여줄게요-!! 

 

 

HomeWidget을 이렇게 바꿔줄게요

 

 

그리고 API응답이 너무 빨라서 로딩이 안보여가지구 

뷰모델이 2초있다가 서비스에게 요청하도록 해줄게요

class HomeViewModel {
  var _service = QuestionService();

  Future<Question> todayQuestion() {
    return Future.delayed(Duration(seconds: 2), () {
      return _service.requestTodayQuestion();
    });
  }
}

 

그러면 로딩 -> 성공 응답 화면 구성이 의도한대로 잘나옵니다 

 

 

이번엔 의도적으로 header값을 안넣어줘서 에러를 일으켜볼게요

로딩 -> 에러 응답 화면 구성도 잘나오네요-!

 

반응형
댓글