컨테이너

[Flutter] StreamBuilder Class 본문

Development/Flutter

[Flutter] StreamBuilder Class

어항 2021. 1. 28. 15:38
반응형

플러터로 개발하면서 비동기 작업을 해보신 적 있으신가요?

 

여기서 비동기란 동시에 일어나지 않는다란 뜻을 가지고 있으며

대표적으로 프로젝트 외부에서 데이터를 가져올 때 발생합니다

(Firebase같은 DB에서 데이터 가져오는 경우, 외부에서 데이터를 크롤링하는 경우 등등)

 

이러한 비동기의 문제는 데이터를 받아오기 전 다음 작업으로 넘어가 내가 원하는 값을 사용할 수 없다는 건데요

쉽게 아래 코드로 확인해보겠습니다

 

import 'dart:async';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String word;

  @override
  void initState() {
    Future.delayed(const Duration(seconds: 2), () {
      word = "확인";
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'StreamBuilder',
      home: Scaffold(
        appBar: AppBar(
          title: Text('StreamBuilder'),
          centerTitle: true,
        ),
        body: Center(
          child: Text(
            (word == null) ? "null" : word,
            style: TextStyle(fontSize: 35),
          ),
        ),
      ),
    );
  }
}

 

이번 예제 코드에선 프로젝트 외부에서 데이터를 가져오는 것이 아닌

Future.delayed로 비동기 문제가 발생되는 상황을 재연합니다

 

Future.delayed는 지정된 시간이 지난 후 특정 코드를 실행시킵니다

위 예제 코드에선 2초 후 word의 값을 "확인"으로 변경합니다

 

 Text 위젯은 word의 값이 null이라면 "null"을 null이 아니라면 자신의 값을 출력합니다

2초가 지나 word의 값이 변하면 Text 위젯의 출력은 "확인"으로 변해야 합니다

 

 

 

하지만 여전히 null을 출력하고 있는데요

 

물론 setState()를 통해 Build 함수를 재호출하면 원하는 값을 Text 위젯으로 출력할 수 있습니다

하지만, 외부에서 데이터를 가져오는데 어느 정도의 시간이 걸리는지 알 수 없으며

데이터를 가져왔더라도 사용자가 지정한 시간까지 강제로 기다려야 합니다

 

이러한 비동기 문제를 쉽게 해결할 수 있는 것이 StreamBuilder입니다

 

 


StreamBuilder

 

예제 코드

import 'dart:async';
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  StreamController<String> streamController = StreamController<String>();

  @override
  void initState() {
    Future.delayed(const Duration(seconds: 2), () {
      streamController.add("확인");
    });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'StreamBuilder',
      home: Scaffold(
        appBar: AppBar(
          title: Text('StreamBuilder'),
          centerTitle: true,
        ),
        body: Center(
            child: StreamBuilder(
          stream: streamController.stream,
          builder: (context, snapshot) {
            if (snapshot.hasData) {
              return Text(
                snapshot.data,
                style: TextStyle(fontSize: 35),
              );
            } else {
              return CircularProgressIndicator();
            }
          },
        )),
      ),
    );
  }
}

 

StreamBuilder는 controller를 사용하여 데이터의 유무를 판단 할 수 있습니다

 

아까의 예제코드와 마찬가지로 첫 실행시 streamController의 데이터는 null 입니다

때문에 builder의 snapshot.hasData가 false이고 CircularProgressIndicator를 반환합니다

 

그리고 2초 후 controller에 "확인"이라는 데이터가 추가되고,

Text 위젯은 그 데이터를 출력합니다

 

 

 

제가 오늘 소개한 StreamBuilder의 사용법은 여러가지의 방법 중 한 가지일 뿐입니다.

더 자세한 정보를 원하신다면 아래 페이지를 참조해주세요

 

 

https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html

 

StreamBuilder class - widgets library - Dart API

Widget that builds itself based on the latest snapshot of interaction with a Stream. Widget rebuilding is scheduled by each interaction, using State.setState, but is otherwise decoupled from the timing of the stream. The builder is called at the discretion

api.flutter.dev

 

반응형
Comments