flutter - ChangeNotifierProvider 사용법 설명.

* provider 가 필요한 이유.
 - 예를 들면 flutter에서 버튼을 클릭한 경우 다른 위젯이나 상위 위젯의 리빌드를 구현하기 위해 필요하다.

* 설명.
 - ChangeNotifierProvider에 ChangeNotifier 상속 받은 클래스를 등록하면 하위 위젯에서 등록한 것을 찾아 사용할 수 있습니다. 즉 상위 위젯에서 하위 위젯으로 흐르는 데이터의 이동 통로를 만든다 생각하면 됩니다.
 - 리빌드가 필요한 위젯을 지정합니다.
  + Consumer, context.watch, Provider.of<Counter>(context, listen: true) 사용.
 - 갱신이 필요한 경우 ChangeNotifierProvider에 등록한 ChangeNotifier 상속 받은 클래스를 찾아 notifyListeners() 호출하면, 위에서 지정한 리빌드가 필요한 위젯을 리빌드 합니다.
  + 데이터 사용은 context.read<Counter>(), Provider.of<Counter>(context, listen: false)으로 합니다. 

* 중요 - 아래 함수의 차이를 알아야 합니다.
 - context.read<Counter>(), Provider.of<Counter>(context, listen: false)
  + 데이터에 접근만 합니다.

 - context.watch, Provider.of<Counter>(context, listen: true), Consumer
  + 데이터에 접근도 하고, notifyListeners() 호출시 리빌하는 위젯을 지정하는 기능도 있습니다.
  + 이 함수나 클래스를 사용하지 않으면 notifyListeners() 호출해도 리빌드 하지 않습니다. 

* 공식 사이트.

* 코드 구현.
 - https://pub.dev/packages/provider/example 의 샘플 코드 입니다.
 - 주석으로 설명 합니다.

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

void main() {
// ChangeNotifierProvider Counter를 등록합니다.
// ChangeNotifierProvider
// "리빌드가 필요한 위젯"과 "등록한 Counter를 받아 사용할 위젯" 중에
// 더 상위 위젯에 등록하면 됩니다.
return runApp(ChangeNotifierProvider(
child: const MyApp(),
create: (BuildContext context) => Counter(),
));
}

// ChangeNotifier 상속 받아 구현합니다.
class Counter with ChangeNotifier {
int _count = 0;

int get count => _count;

void increment() {
_count++;
// 중요 - notifyListeners를 호출해야 리빌드가 됩니다.
notifyListeners();
}
}

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

@override
Widget build(BuildContext context) {
return const MaterialApp(
home: MyHomePage(),
);
}
}

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

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Example'),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: const <Widget>[
Text('You have pushed the button this many times:'),
CountWidget(),
// 중복해서 사용해도 양쪽다 리빌드 됩니다.
CountWidget(),
],
),
),
floatingActionButton: FloatingActionButton(
key: const Key('increment_floatingActionButton'),

// context.read 는 위젯을 리빌드하지 않습니다.
// increment()에서 notifyListeners()를 호출해도
// 이 부분은 리빌드 하지 않습니다.
// 아래 코드는 context.read와 동일 합니다.
// Provider.of<Counter>(context, listen: false)
onPressed: () => context.read<Counter>().increment(),
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}

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

@override
Widget build(BuildContext context) {
return Text(

// context.watch Counter클래스의 데이터에 접근 기능도 있지만
// 이와 동시에 리빌드가 필요한 곳이라고 지정하는 기능도 합니다.
// 아래 코드는 context.watch와 동일 합니다.
// Provider.of<Counter>(context, listen: true)
'${context.watch<Counter>().count}',
key: const Key('counterState'),
style: Theme.of(context).textTheme.headline4);
}

/// 위 코드와 동일한 역할을 하는 코드입니다.
/// context.watch<Counter>() Consumer로 구현한 코드 입니다.
/// context.watch, Consumer
/// ChangeNotifierProvider에 등록한 Counter에 접근할 수 있고,
/// Counter에서 notifyListeners()호출시
/// 리빌드 하는 위젯을 표시하는 두가지 기능을 합니다.
// return Consumer<Counter>(builder: (context, counter, child) {
// return Text(
// '${counter.count}',
// key: const Key('counterState'),
// style: Theme.of(context).textTheme.headline4);
// });

}

 

댓글

이 블로그의 인기 게시물

파이썬 vscode에서 자동 코드 정렬. Formatter.

Unity3D git 저장소에 올릴때 필요없는 파일 제외하기. gitignore

플러터(flutter) 개발 참고 사이트들.