ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Flutter]플러터 Futurebuilder / Streambuilder란??
    플러터 Flutter 2021. 5. 30. 17:43
    반응형

    아직까지 나도 제대로 적용한적은 없고 그냥 구글링하면서 학습겸 정리하였다.

    - FutureBuilder 공식문서 바로가기
      앨범에서 이미지 가져오기, 배터리 표시, 파일 가져오기, http요청등 일회성 응답에 사용

    - StreamBuilder 공식문서 바로가기
      위치 업데이트, 음악 재생, 스톱워치 일부 데이터를 여러번 가져올때 사용


    둘다 코드를 읽고 error data 받는다.

    - FutureBuilder 샘플코드
      코드를 복사해서 실행하면 2초 로드후 데이터를 가져왔다는 성공 메시지를 띄우는 예제이다.

       ※FutureBuilderStatefulWidget의 자식클래스이다.

    1. FutureBuilder

    import 'package:flutter/material.dart';
    
    void main() => runApp(const MyApp());
    
    /// This is the main application widget.
    class MyApp extends StatelessWidget {
      const MyApp({Key? key}) : super(key: key);
    
      static const String _title = 'Flutter Code Sample';
    
      @override
      Widget build(BuildContext context) {
        return const MaterialApp(
          title: _title,
          home: MyStatefulWidget(),
        );
      }
    }
    
    /// This is the stateful widget that the main application instantiates.
    class MyStatefulWidget extends StatefulWidget {
      const MyStatefulWidget({Key? key}) : super(key: key);
    
      @override
      State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
    }
    
    /// This is the private State class that goes with MyStatefulWidget.
    class _MyStatefulWidgetState extends State<MyStatefulWidget> {
      final Future<String> _calculation = Future<String>.delayed(
        const Duration(seconds: 2),
        () => 'Data Loaded',
      );
    
      @override
      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) { //data가 있으면  snapshot.data
              List<Widget> children;
              if (snapshot.hasData) {
                children = <Widget>[
                  const 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>[
                  const Icon(
                    Icons.error_outline,
                    color: Colors.red,
                    size: 60,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 16),
                    child: Text('Error: ${snapshot.error}'),
                  )
                ];
              } else {
                children = const <Widget>[
                  SizedBox(
                    child: CircularProgressIndicator(),
                    width: 60,
                    height: 60,
                  ),
                  Padding(
                    padding: EdgeInsets.only(top: 16),
                    child: Text('Awaiting result...'),
                  )
                ];
              }
              return Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: children,
                ),
              );
            },
          ),
        );
      }
    }
    

    - 간단한 예제

     

    class Sample extends StatelessWidget { 
    	@override 
    	Widget build(BuildContext context) { 
        
        	return FutureBuilder<SharedPreferences>( 
            	future: SharedPreference.getInstance(), 
                builder: (BuildContext context, AsyncSnapshot<SharedPreferences> snapshot) { 
               		String result; 
                   	if (snapshot.hasData == false) { 
                    	result = "Loading..."; } 
                  	else if (snapshot.data.getString("sessionKey")) { 
                    	result = "You has session key."; 
                  	} else { 
                    	result = "You has not session key."; 
                  	} return Center( child: Text(result); ); 
            	} 
         	) 
     	} 
    }
    

    Async/await 키워드를 사용하여 비동기를 처리하는 것을 직관적으로 코드를 작성할 수 있다. FutureBuilder<T>에서 <T>는 비동기로 처리할 타입이 된다. builder에서는 AsyncSnapshot<T>인자를 통해서 <T>에 넘겨진 타입이 비동기로 처리되는 동안의 상태를 처리한다. 

     

    2. StreamBuilder

    Stream?

    스트림은 데이터가 들어오고 나가는 통로다.데이터가 변하는 걸 보고 있다가 그에 맞춰 적절한 처리.. 필터링(where)이나 수정(map), 버퍼링(take)같은 일을 한다.

    StreamController?

    스트림 컨트롤러는 여러 리스너(구독&상태)을 관리한다. 

    - 아래의 예제는 값이 추가 될때마다 출력하는 소스이다.

    void main() {
      StreamController ctrl = StreamController();
    ​
      ctrl.stream.listen((data) {
        print(data);
      });
    ​
      ctrl.add(1);
      ctrl.add("Hello Stream");
      ctrl.add({"first": 10, "tow": "20"});
    ​
      ctrl.close();
    }

    플러터에서는 스트림 빌더(StreamBuilder)를 써서 스트림 처리를 한다.
    스트림 빌더를 쓰면 setState() 를 쓰지 않고도 UI를 업데이트 할 수 있다.
    또 항상 스트림의 최신값을 가져오니, 최신값을 확인할 필요가 없다.

    - StreamBuilder 예제

    import 'dart:async';
    
    import 'package:flutter/material.dart';
    
    void main() => runApp(new MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          title: 'Flutter Demo',
          theme: new ThemeData(
            primarySwatch: Colors.blue,
          ),
          home: new MyHomePage(),
        );
      }
    }
    
    class MyHomePage extends StatefulWidget {
      @override
      _MyHomePageState createState() => new _MyHomePageState();
    }
    
    class _MyHomePageState extends State<MyHomePage> {
      int _counter = 0;
      StreamController<int> _events;
    
      @override
      initState() {
        super.initState();
        _events = new StreamController<int>();
        _events.add(0);
      }
    
      void _incrementCounter() {
          _counter++;
          _events.add(_counter);
        
      }
    
      @override
      Widget build(BuildContext context) {
        return new Scaffold(
          appBar: new AppBar(
            title: new Text("StreamBuilder test"),
          ),
          body: new Center(
            child: new Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Text(
                  'You have pushed the button this many times:',
                ),
                StreamBuilder(
                  stream: _events.stream,
                  builder: (BuildContext context, snapshot) {
                    return new Text(
                      snapshot.data.toString(),
                      style: Theme.of(context).textTheme.display1,
                    );
                  },
                ),
              ],
            ),
          ),
          floatingActionButton: new FloatingActionButton(
            onPressed: _incrementCounter,
            tooltip: 'Increment',
            child: new Icon(Icons.add),
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }

     

    본문의 참조

    https://zerodice0.tistory.com/225
    https://ahang.tistory.com/16
    https://eunjin3786.tistory.com/272

    반응형

    댓글

Designed by Tistory.