본문 바로가기

Flutter/00 초보때 작성글

[Flutter] Provider with Flutter sample - ChangeNotifierProvider

원본영상(www.youtube.com/watch?v=HkPxVvv9ul4&list=PLwUg6hFuXV86arSYNF9x_5Vm_lKdIBpf9&index=53)

 

Provider 샘플입니다 - ChangeNotifierProvider

버전은 provider: ^5.0.0

 

counter.dart 코드 

 

import 'package:flutter/foundation.dart';

class Counter with ChangeNotifier{
  int _count =0;

  int getCount() => _count;

  void incrementCount() {
    _count++;
    notifyListeners(); // 변경시 알람을 전송하는 역할
  }
}

 

main.dart 코드

 

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: ChangeNotifierProvider<Counter>( // 4.0 이후부터 create 사용.
          create: (_) => Counter(),
//        builder: (BuildContext context) => Counter(), // 4.0 이후 삭제됨
          child: MyHomePage(title: 'Flutter Demo Home Page')),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

// provider 로 구현하면서 삭제 처리
//  int _counter = 0;
//  void _incrementCounter() {
//    print('click _incrementCounter()-->setState()');
//    setState(() {
//      _counter++;
//    });
//  }

  @override
  Widget build(BuildContext context) {
    print('start build()');

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text(
              'You have pushed the button this many times:',
            ),
            // Consumer 특징
            // 사용할 위젯을 감싸서 사용
            // context 를 알아서 찾아서 사용함
            // listen 선택 옵션이 없음
            Consumer<Counter>(
              builder: (context, value, child) => Text(
//              '$_counter', // provider 로 구현하면서 삭제 처리
                value.getCount().toString(),
                style: Theme.of(context).textTheme.headline4,
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        // Provider.of 특징
        // 값을 바로 가져오기때문에 위젯 감싸기 없이 직접 입력.
        // ChangeNotifierProvider 의 context 를 MyHomePage 제공 => build => Provider.of 사용
        // 만약에 ChangeNotifierProvider 가 MaterialApp 위에 정의되면 context 를 찾지 못해서 오류 발생
        // 에러 발생시 context 를 어디서 전달받는지 확인 필수, 오류 발생 제일 많음
        // listen 선택 옵션이 있음
        onPressed: () => Provider.of<Counter>(context, listen: false).incrementCount(),
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ), // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

 

Flutter 샘플 코드를 이용하여 provider 구현한 샘플입니다.

StatefulWidget 이지만, setState() 를 사용하지 않아서 print('start build()'); 구문이 최초에만 실행됨.

 

각 옵션의 특징은

Consumer - 대상 위젯을 감싸서 사용, context 를 알아서 찾아감, listen 선택 옵션없음, Text 관련 위젯에 적합

Provider.of - 직접 사용(위젯 감싸기 X), context 위치를 잘 선택해야함, listen 선택 옵션 있음, 함수/메소드 구현시 적합