의존성 주입 (binding)

controller를 인스턴스화 하는 방법 ( 의존성 주입 )

put, lazyput, putasync, create 방법이 있음

binding 방법

특정 페이지 안에서 특정 페이지로 이동할때 바인딩

Get.put

  • 페이지 이동시 create, initialized 되고 페이지에서 나올때 delete()가 실행되며 메모리에서 삭제
RaisedButton(
  child: Text("GetPut"),
  onPressed: () {
    //바인딩 : 페이지로 보내주면서 사용할 컨트롤러를 주입하는 방법
    Get.to(
      GetPut(),
      binding: BindingsBuilder(() {
        Get.put(DependencyController());
        //put방식은 페이지 이동시 controller를 메모리에 올려주고 나올땐 알아서 삭제해줌
      }),
    );
  },
),

Get.lazyPut

  • 버튼을 눌러 페이지 이동했을 당시에는 create, initialized되지 않지만 사용할때 생성됨
  • 나올때는 put과 동일하게 삭제
RaisedButton(
  child: Text("Get.lazyPut"),
  onPressed: () {
    Get.to(
      GetLazyPut(),
      binding: BindingsBuilder(() {
        // controller를 사용할때 메모리에 올려줌
        // 나올땐 삭제
        Get.lazyPut<DependencyController>(
            () => DependencyController());
      }),
    );
  },
),

Get.putAsync

  • 페이지에 접근을 할때 비동기식으로 데이터를 받아오거나 가공처리를 오랫동안하고 나서 컨트롤러를 인스턴스화 할때 사용
RaisedButton(
  child: Text("Get.putAsync"),
  onPressed: () {
    Get.to(
      GetPut(),
      binding: BindingsBuilder(() {
        // 페이지에 접근을 할때 비동기식으로 데이터를 받아오거나 가공처리를 오랫동안하고 나서 컨트롤러를 인스턴스화 할때 사용
        Get.putAsync<DependencyController>(() async {
          // 데이터 처리 후 인스턴스화
          await Future.delayed(Duration(seconds: 5));
          return DependencyController();
        });
      }),
    );
  },
),

Get.create

  • 페이지 이동 할 당시에는 생성 안되지만 사용할때 마다 생성됨
  • 자동으로 삭제되지 않기 때문에 사용 종료때마다 삭제 해줘야함
RaisedButton(
  child: Text("Get.create"),
  onPressed: () {
    // 인스턴스를 여러개 생성
    Get.to(GetPut(), binding: BindingsBuilder(() {
      // 사용할때성 마다 인스턴스 생성
      Get.create<DependencyController>(
          () => DependencyController());
    }));
  },
),

앱이 실행될 때 가장 앞에서 바인딩 설정

  • 라우팅 설정의 GetPage안에서 설정
getPages: [
  GetPage(
    name: '/binding',
    page: () => BindingPage(),
    binding: BindingsBuilder(() {
      Get.put(CountControllerWithGetX());
    }),
  ),
],

Bindings를 implements한 클래스를 만들어서 getPages의 binding에 넣어줄 수 있음

class BindingPageBinding implements Bindings {
  @override
  void dependencies() {
    // TODO: implement dependencies
    Get.put(CountControllerWithGetX());
  }
}
GetPage(
  name: '/binding',
  page: () => BindingPage(),
  binding: BindingPageBinding(),
),

참고

https://www.youtube.com/watch?v=KDTjo-6jFKs 

 

728x90

값이 변경되어야만 update (rebuild)를 합니다.

현재 상태값과 변경될 상태값이 동일하다면 wiget을 다시 그리지 않습니다.

controller

class CountControllerWithReactive {
  RxInt count = 0.obs; // 반응형 상태관리
  void increase() {
    count++;
  }

    // 값을 넣어 줄때
  void putNumber(int value) {
    count(value);
  }
}

ui

class ReactiveSimpleStatePage extends StatelessWidget {
  const ReactiveSimpleStatePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    Get.put(CountControllerWithReactive());
    return Scaffold(
        appBar: AppBar(
          title: Text('반응형 상태 관리'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                "GetX",
                style: TextStyle(fontSize: 50),
              ),
                            // 현재 값이 5인 경우 putNumber(5)를 아무리 눌러도 다시 그려지지 않음
              Obx(() => Text(
                    "${Get.find<CountControllerWithReactive>().count.value}",
                    style: TextStyle(fontSize: 50),
                  )),
              RaisedButton(
                onPressed: () {
                  Get.find<CountControllerWithReactive>().increase();
                },
                child: Text(
                  "+",
                  style: TextStyle(fontSize: 50),
                ),
              )
              RaisedButton(
                onPressed: () {
                  Get.find<CountControllerWithReactive>().putNumber(5);
                },
                child: Text(
                  "5로 변경",
                  style: TextStyle(fontSize: 50),
                ),
              ),
            ],
          ),
        ));
  }
}

이벤트 트리거

controller

import 'package:get/get.dart';

// trigger를 위해 getxcontroller 상속
class CountControllerWithReactive extends GetxController {
  RxInt count = 0.obs; // 반응형 상태관리
  void increase() {
    count++;
  }

  void putNumber(int value) {
    count(value);
  }

  // getxcontroller lifecycle
  @override
  void onInit() {
    // TODO: implement onInit
    // worker
    // 매번 값이 변경될 때 마다 호출 (반응 상태일때만 가능)
    ever(count, (_) => print("매번 호출"));
    // 한번만 호출
    once(count, (_) => print("한번만 호출"));
    // 이벤트가 끝났을때 실행
    debounce(count, (_) => print("마지막 변경에 한번만 호출"), time: Duration(seconds: 1));
    // 변경되고 있는 동안 설정한 초마다 실행
    interval(count, (_)=>print("변경되고 있는 동안 1초마다 호출"),time: Duration(seconds: 1));
    super.onInit();
  }

  @override
  void onClose() {
    // TODO: implement onClose
    super.onClose();
  }
}

custom Rx 타입

enum 타입

enum NUM {FIRST, SECOND}
class controller {
    Rx<NUM> nums = NUM.FIRST.obs;

    void put(){
        nums(NUM.SECOND);
    }
}

class 타입

class User{
    String name;
    int age;
}
class controller {
    Rx<User> user = User().obs;

    void put(){
        user(User());
        user.update((_user){
            _user.name = 'name';
        });
    }
}

list 타입

class controller {
    RxList<String> list = [].obs;
    void put(){
        list.addAll();
        list.add();
        list.addIf(user.value.name=='name','okay'); // 조건, 대입값
    }
}

 

참고

https://www.youtube.com/watch?v=TjC1ka8fZJw 

 

728x90

단순 상태 관리 앱 화면

main(controller 등록)

class SimpleStatePage extends StatelessWidget {
  const SimpleStatePage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
        // getx controller 등록
        Get.put(CountControllerWithGetX());
    return Scaffold(
        appBar: AppBar(
          title: Text('단순 상태 관리'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Expanded(child: WithGetX()),
              Expanded(
                                    // provider controller 등록
                  child: ChangeNotifierProvider<CountControllerWithProvider>(
                create: (_) => CountControllerWithProvider(),
                child: WithProvider(),
              )),
            ],
          ),
        ));
  }
}

Provider

controller

class CountControllerWithProvider extends ChangeNotifier {
  int count = 0;
  void increase() {
    count++;
    notifyListeners();
  }
}

ui

class WithProvider extends StatelessWidget {
  const WithProvider({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        children: [
          Text(
            "Provider",
            style: TextStyle(fontSize: 50),
          ),
          Consumer<CountControllerWithProvider>(
            builder: (_, snapshot, child) {
              return Text("${snapshot.count}", style: TextStyle(fontSize: 50));
            },
          ),
          RaisedButton(
            onPressed: () {
              // listen: false를 줘서 consumer 부분만 rebuild
              Provider.of<CountControllerWithProvider>(context, listen: false)
                  .increase();
            },
            child: Text(
              "+",
              style: TextStyle(fontSize: 50),
            ),
          ),
        ],
      ),
    );
  }
}

GetX

controller

class CountControllerWithGetX extends GetxController {
  int count = 0;
  void increase() {
    count++;
    update();
  }
}

ui

class WithGetX extends StatelessWidget {
  const WithGetX({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            "GetX",
            style: TextStyle(fontSize: 50),
          ),
          GetBuilder<CountControllerWithGetX>(builder: (controller) {
            return Text(
              "${controller.count}",
              style: TextStyle(fontSize: 50),
            );
          }),
          RaisedButton(
            onPressed: () {
              Get.find<CountControllerWithGetX>().increase();
            },
            child: Text(
              "+",
              style: TextStyle(fontSize: 50),
            ),
          ),
        ],
      ),
    );
  }
}

비교

Provider는 consumer를 이용해 상태값을 가져오고 provider와 context를 이용해 controller의 비즈니스 로직을 불러옵니다.

GetX는 GetBuilder를 통해 상태값을 가져오고 Get.find를 통해 controller의 비즈니스 로직을 가져옵니다.

context를 사용하지 않는 GetX 방식은 위젯으로 분리하여 사용가능합니다.

...{
    ...
    return (
    ...,
    buildRaisedButton(),
    );

    Widget buildRaisedButton() {
      return RaisedButton(
        onPressed: () {
          Get.find<CountControllerWithGetX>().increase();
        },
        child: Text(
          "+",
          style: TextStyle(fontSize: 50),
        ),
      );
    }

}

반면, provider의 경우에는 stateful 위젯으로 변경하거나 context를 넘져워야합니다.

    buildRaisedButton(context),
            ],
          ),
        );
      }

  Widget buildRaisedButton(BuildContext context) {
    return RaisedButton(
          onPressed: () {
            // listen: false를 줘서 consumer 부분만 rebuild
            Provider.of<CountControllerWithProvider>(context, listen: false)
                .increase();
          },
          child: Text(
            "+",
            style: TextStyle(fontSize: 50),
          ),
        );
  }
}

GetX는 선언이 자유롭다.

부모에서 controller를 선언해줄 필요가 없습니다.

ui 부분에서 바로 사용 가능

class WithGetX extends StatelessWidget {
  const WithGetX({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
        // 바로 사용 가능
        Get.put(CountControllerWithGetX());
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            "GetX",
            style: TextStyle(fontSize: 50),
          ),
          GetBuilder<CountControllerWithGetX>(builder: (controller) {
            return Text(
              "${controller.count}",
              style: TextStyle(fontSize: 50),
            );
          }),
          RaisedButton(
            onPressed: () {
              Get.find<CountControllerWithGetX>().increase();
            },
            child: Text(
              "+",
              style: TextStyle(fontSize: 50),
            ),
          ),
        ],
      ),
    );
  }
}

또한 클래스가 생성될때 바로 사용가능합니다.

class WithGetX extends StatelessWidget {
  const WithGetX({Key? key}) : super(key: key);
    // 클래스가 생성될때 바로 사용가능
    CountControllerWithGetX _countControllerWithGetX =Get.put(CountControllerWithGetX());
  @override
  Widget build(BuildContext context) {

    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            "GetX",
            style: TextStyle(fontSize: 50),
          ),
          GetBuilder<CountControllerWithGetX>(builder: (controller) {
            return Text(
              "${controller.count}",
              style: TextStyle(fontSize: 50),
            );
          }),
          RaisedButton(
            onPressed: () {
                            //find를 할 필요가 없음
              _countControllerWithGetX.increase();
            },
            child: Text(
              "+",
              style: TextStyle(fontSize: 50),
            ),
          ),
        ],
      ),
    );
  }
}

특정 컨트롤러에 아이디를 부여해서 관리 가능

cotroller

class CountControllerWithGetX extends GetxController {
  int count = 0;
    // id를 받아서 update에 배열로 넣어줌
  void increase(String id) {
    count++;
    update([id]);
  }
}

ui

class WithGetX extends StatelessWidget {
  WithGetX({Key? key}) : super(key: key);
  CountControllerWithGetX _countControllerWithGetX =
      Get.put(CountControllerWithGetX());

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Text(
            "GetX",
            style: TextStyle(fontSize: 50),
          ),
          GetBuilder<CountControllerWithGetX>(
                        // id 추가
            id: "first",
            builder: (controller) {
              return Text(
                "${controller.count}",
                style: TextStyle(fontSize: 50),
              );
            },
          ),
          GetBuilder<CountControllerWithGetX>(
            id: "second",
            builder: (controller) {
              return Text(
                "${controller.count}",
                style: TextStyle(fontSize: 50),
              );
            },
          ),
          buildRaisedButton("first"),
          buildRaisedButton("second"),
        ],
      ),
    );
  }

  Widget buildRaisedButton(String id) {
    return RaisedButton(
      onPressed: () {
                // id를 넘겨줌
        _countControllerWithGetX.increase(id);
      },
      child: Text(
        "+",
        style: TextStyle(fontSize: 50),
      ),
    );
  }
}

참고

https://www.youtube.com/watch?v=k3hgQu6it4c 

 

728x90

GetX packages

https://pub.dev/packages/get

 

get | Flutter Package

Open screens/snackbars/dialogs without context, manage states and inject dependencies easily with GetX.

pub.dev

 

기본 페이지 라우팅

main.dart - GetMaterialApp 사용

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Home(),
    );
  }
}

Page 이동

기존 라우팅

Navigator.of(context).push(MaterialPageRoute(builder: (_) => FirstPage()));

GetX 라우팅

Get.to(() => FirstPage());

뒤로 이동

기존 라우팅

Navigator.of(context).pop();

GetX 라우팅

Get.back();

페이지 이동시 이전 히스토리 삭제

기존 라우팅

Navigator.of(context).pushAndRemoveUntil(
                      MaterialPageRoute(builder: (_) => Home()),
                      (route) => false);

GetX 라우팅

Get.offAll(Home());

Named 페이징 라우팅

Named route 정의

main.dart

기존 라우팅

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      routes: {
        '/': (context) => Home(),
        '/first': (context) => FirstNamedPage(),
        '/second': (context) => SecondNamedPage(),
      },
    );
  }
}

GetX 라우팅

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      getPages: [
        GetPage(name: '/', page: () => Home()),
        GetPage(name: '/first', page: ()=>FirstNamedPage()),
        GetPage(name: '/second', page: ()=>SecondNamedPage()),
      ],
    );
  }
}

Page 이동

기존 라우팅

Navigator.of(context).pushNamed('/first');

GetX 라우팅

Get.toNamed('/first');

GetX 라우팅 현재페이지 삭제 후 이동

Get.offNamed('/second'); // /first페이지 삭제 후 /second 이동

페이지 이동시 이전 히스토리 삭제

기존 라우팅

Navigator.pushNamedAndRemoveUntil(context, '/', (route) => false);

GetX 라우팅

Get.offAllNamed('/');

페이지 전환 효과 적용

GetX

getPages의 transition 속성 지정

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return GetMaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      initialRoute: '/',
      getPages: [
        GetPage(name: '/', page: () => Home(), transition: Transition.zoom),
        GetPage(
            name: '/first',
            page: () => FirstNamedPage(),
            transition: Transition.zoom),
        GetPage(
            name: '/second',
            page: () => SecondNamedPage(),
            transition: Transition.zoom),
      ],
    );
  }
}

arguments 전달

GetX

// 전달할때
Get.toNamed('/first', arguments: "argument");
Get.to(FristPage(),arguments: 3);
Get.toNamed('/first', arguments: {"name":"name", "num":"11"});

// 받을때
Text("${Get.arguments}"),
Text("${Get.arguments.toString()}"),
Text("${Get.arguments['name']}"),

GetX 객체 전달

// 객체전달
class User {
  String name;
  int age;
  User(this.name, this.age);
}

Get.toNamed('/next', arguments: User("name", 11));

// 객체받기
Text("${(Get.arguments as User).name} : ${(Get.arguments as User).age} "),

동적 링크 사용

동적 링크 정의

GetPage(
  name: '/user/:uid', 
  page: () => UserPage(),
  transition: Transition.zoom)

파라미터 전달

Get.toNamed('/next/28353');

파라미터 받기

Text("${Get.parameters['uid']}"),

복잡한 파라미터 전달

Get.toNamed('/next/28353?name=name&age=11');

복잡한 파라미터 받기

Text("${Get.parameters['uid']}"),
Text("${Get.parameters['name']}"),
Text("${Get.parameters['age']}"),

참고

https://www.youtube.com/watch?v=OXfG-D4PNpQ 

 

728x90

BLOC

Bussiness Logic Component

비즈니스 로직과 ui를 구분 짓고 필요에 따라 원하는 부분만 데이터 처리

실 사용 예제

버튼 클릭시 증감

1. Stateful version

ui widget - 버튼 클릭시 증감

//stateless widget으로 count를 보내 화면에 그려줌
body: CountViewStateless(count: count),
floatingActionButton: Row(
  mainAxisAlignment: MainAxisAlignment.end,
  children: [
    IconButton(
      icon: Icon(Icons.add),
      onPressed: () {
        setState(() {
          count++;
        });
      },
    ),
    IconButton(
      icon: Icon(Icons.remove),
      onPressed: () {
        setState(() {
          count--;
        });
      },
    ),
  ],
),

view - 결과 출력

import 'package:flutter/material.dart';

class CountViewStateless extends StatelessWidget {
  int count;
  CountViewStateless({Key key, this.count}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    print("CountViewStateless Build !!");
    return Center(
        child: Text(
      count.toString(),
      style: TextStyle(fontSize: 80),
    ));
  }
}

2. bloc pattern

ui widget - 값을 변경시키는 이벤트 발생

// 전역변수로 bloc 생성
CountBloc countBloc;

class _BlocDisplayWidgetState extends State<BlocDisplayWidget> {
  @override
  void initState() {
    super.initState();
        // bloc
    countBloc = CountBloc();
  }

  @override
  void dispose() {
    super.dispose();
        // bloc 종료
    countBloc.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("bloc 패턴"),
      ),
      body: CountView(),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
                            // add는 이벤트를 등록한다는 의미
                            // 숫자를 더하거나 빼는 로직이 현재파일에는 존재하지 않음
              countBloc.countEventBloc.countEventSink.add(CountEvent.ADD_EVENT);
            },
          ),
          IconButton(
            icon: Icon(Icons.remove),
            onPressed: () {
              countBloc.countEventBloc.countEventSink
                  .add(CountEvent.SUBTRACT_EVENT);
            },
          ),
        ],
      ),
    );
  }
}

count_bloc - 비즈니스 로직 처리

import 'dart:async';

//bloc
class CountBloc {
  CountEventBloc countEventBloc = CountEventBloc();
  int _count = 0;
    // broadcast를 넣어주면 여러군데에서 구독 가능
  final StreamController<int> _countSubject = StreamController<int>.broadcast();

    // count는 _countSubject.stream를 구독하고 있는 모든 widget에게 변경된 상태값을 전달
  Stream<int> get count => _countSubject.stream;

    // 생성자
  CountBloc() {
        // countEventBloc의 _countEventSubject을 구독
    countEventBloc._countEventSubject.stream.listen(_countEventListen);
  }
    // 생성자에서 변화를 감지하여 listen으로 리턴 받은 것
    // 인자값 event에 해당하는 것은 enum에 등록된 이벤트 
  _countEventListen(CountEvent event) {
        // 비즈니스 로직 부분
    switch (event) {
      case CountEvent.ADD_EVENT:
        _count++;
        break;
      case CountEvent.SUBTRACT_EVENT:
        _count--;
        break;
    }
        // 결과값인 _count를 sink에 add로  넣어줌 
    _countSubject.sink.add(_count);
  }

  dispose() {
    _countSubject.close();
    countEventBloc.dispose();
  }
}

// event 
class CountEventBloc {
  final StreamController<CountEvent> _countEventSubject =
      StreamController<CountEvent>();
    // event 값이 sink로 들어오면 _countEventSubject를 통해 구독자에게 알려줌  
  Sink<CountEvent> get countEventSink => _countEventSubject.sink;

  dispose() {
    _countEventSubject.close();
  }
}

// event에 해당하는 enum
enum CountEvent { ADD_EVENT, SUBTRACT_EVENT }

count_view 결과값 받아오는 곳

StreamBuilder(
    // stream을 리스닝 
  stream: countBloc.count, // Stream<int> get count => _countSubject.stream; 구독
  initialData: 0,
    // snapshot으로 값이 들어옴
  builder: (BuildContext context, AsyncSnapshot<int> snapshot) { 
    if (snapshot.hasData) {
      return Text(
        snapshot.data.toString(),
        style: TextStyle(fontSize: 80),
      );
    }
    return CircularProgressIndicator();
  },
),

3. Skip event bloc pattern

ui 위와 다르게 바로 이벤트 호출함

class _BlocDisplayWidgetState extends State<BlocDisplayWidget> {
  @override
  void initState() {
    super.initState();
    countBloc = CountBloc();
  }

  @override
  void dispose() {
    super.dispose();
    countBloc.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("bloc 패턴"),
      ),
      body: CountView(),
      floatingActionButton: Row(
        mainAxisAlignment: MainAxisAlignment.end,
        children: [
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () {
                            // 이벤트 호출
              countBloc.add();
            },
          ),
          IconButton(
            icon: Icon(Icons.remove),
            onPressed: () {
              countBloc.subtract();
            },
          ),
        ],
      ),
    );
  }
}

count_bloc - skip event 비즈니스 로직 처리

import 'dart:async';

class CountBloc {
  int _count = 0;
  final StreamController<int> _countSubject = StreamController<int>.broadcast();
  Stream<int> get count => _countSubject.stream;

  add() {
    _count++;
    _countSubject.sink.add(_count);
  }

  subtract() {
    _count--;
    _countSubject.sink.add(_count);
  }

  dispose() {
    _countSubject.close();
  }
}

참고

https://www.youtube.com/watch?v=AY6i0a4BM7o 

 

728x90

Future 함수 정의

Future<String> myFuture() async{
    await Future.delayed(Duration(seconds: 2));
    return 'another Future completed';
}

FutureBuilder 소스코드 확인

FutureBuilder 인자값 확인 -> future, builder 정의 예정

builder메서드는 아래와 같이 context와 snapshot을 인자값으로 가지고 있음

snapshot은 특정 시점에 데이터를 복사해서 보관하는 것

snapshot이 복사해서 가지고 있는 future 데이터가 실제로 존재하는지 확인 필요

소스코드를 보면 builder는 AsyncSnapshot객체와 함께 제공되는데 이 객체는 connectionState에 3가지 중 한가지 속성을 가진다고 나와있음 → 없을때, 대기중일때 완료되었을때

future가 완료된 상태에서만 화면에 ui를 그릴수 있도록 조건식 생성, 데이터가 아직 도착하지 않았다면 대기중 표시

FutureBuilder(
    future: myFuture(),
    builder: (context, snapshot){
        // future가 완료된 상태일때
        if(snapshot.connectionState == ConnectionState.done){
            return Text(
                snapshot.data,
            );
        }
        // 완료된 상태가 아닐때 progress 출력
        return CircularProgressIndicator();
    }
)
728x90

+ Recent posts