Provider를 이용해 상태관리 하는법을 알아보자.
Provider
는 App State를 관리하기 위해 Flutter에서 제공하는 라이브러리다. Provider
외에도 사용할 수 있는 방법은 많이 존재한다. 대표적으로 많이 쓰이기에 가장 먼저 정리해보려 한다.
Provider에 많은 요소들 중 4가지 요소만 살펴보려한다.
1. ChangeNotifier
2. ChangeNotifierProvider
3. Consumer
4. Provider.of
먼저 Provider
를 사용하기 위해서는 pubspec.yaml에 의존성을 추가해야한다.
dependencies:
flutter:
sdk: flutter
provider: ^<latest vesion>
dev_dependencies:
변경사항을 알릴 수 있는 클래스. notifyListener()
를 사용하면 ChangeNotifier
를 구독하고 있는 Listener에게 변경사항이 전달된다. 아래는 이해를 돕기 위한 에제이다.
class CounterProvider with ChangeNotifier, DiagnosticableTreeMixin {
int _count = 0;
int get count => _count;
void increment() { //증가 함수
_count++;
notifyListeners(); //이 함수를 통해 화면 상태 변경을 리스너에게 전달한다.
}
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
// TODO: implement debugFillProperties
super.debugFillProperties(properties);
properties.add(IntProperty('count', count)); //property 제공을 위한 count add
}
}
추가적으로 ChangeNotifier는 flutter:foundation에 존재하고 고수준 클래스(ex: Widget, etc)에 의존성이 없어서 테스트하기가 쉽다.
ChangeNotifierProvider
는 ChangeNotifier를 하위 항목에 제공하는 위젯이다. 아까전에 notifyLisner를 통해 ChangeNotifier를 구독하고 있는 Listner에게 변경사항이 전달된다고 했는데, ChangeNotifierProvider
는 하위 항목들에게 ChangeNotifier를 제공하여 구독할 수 있도록 해준다. 아래는 ChangeNotifierProvider
를 선언하는 예제이다.
void main() {
runApp(
ChangeNotifierProvider(
create: (_) => CounterProvider()), // Provider를 사용하기 위한 Provider선언
child: const MyApp(),
),
);
}
ChangeNotifierProvider
는 똑똑해서 CounterProvider의 Instance를 잘 관리해준다. CounterProvider의 Instance를 굳이 다시 rebuild 할 필요가 없고, dispose()도 적절한 시점에 자동으로 호출한다.
Provider를 여러개 선언하고 싶을 때는 MultiProvider를 사용하면 된다. 아래는 예제이다.
void main() {
runApp(
MultiProvider(providers: [ //Provider를 여러개 사용시 MultiProvider
ChangeNotifierProvider(create: (_) => CounterProvider()), // Provider를 사용하기 위한 Provider선언
],
child: const MyApp(),
),
);
}
Consumer
는 ChangeNotifierProvider에서 하위 항목에서 ChangeNotifier에 접근할 수 있게 한다.
return HumongousWidget(
child: AnotherMonstrousWidget(
child: Consumer<CounterProvider>(
builder: (context, countmodel, child){
return Text('${countmodel.count}');
},
),
),
),
지정한 ChangeNotifier의 이름인 CounterProvider를 Consumer<>안에 넣어준다. Consumer
위젯의 필수 인자인 builder 함수는 3가지 인수로 작동된다.
Provider.of
도 Consumer와 같이 ChangeNotifier를 구독하고 있는 Listener이다. Consumer와 다른 점은 Provider.of
는 위젯이 아니라 ChangeNotifier 그 자체를 반환한다. 아래는 예제이다.
class Count extends StatelessWidget { // Count 개수를 표한하는 부분을 필요없는 rebuild를 없애기 위해 따로 위젯화
const Count({Key? key}) : super(key: key);
var counts = Provider.of<CounterProvider>(context); //CounterProvider를 반환하기 위한 Provider.of 사용
Widget build(BuildContext context) {
return Text(
counts.count, //CounterProvider 안에 있는 count 상태 읽어오기.
key: const Key('counterState'),
);
}
}
만약 ChangeNotifier에서 notifyListener()가 호출되면 해당 StatelessWidget의 build()가 다시 호출됩니다. 만약 StatefulWidget이라면 State.didChangeDependencies가 호출된다.
Provider에 대하여 더 궁금한 부분은 아래 공식문서를 읽어보자.
Provider Flutter 공식문서 (API docs)