Provider는 플러터의 기본 위젯은 Inherited 위젯을 기반으로 한 상태 관리 패키지다
Provider는 앞서 배운 Bloc과 비슷하게 상태 공유 말고도 관심사를 불리할 수 있다는 필요성이 있다
dependencies:
flutter:
sdk: flutter
provider: ^5.0.0
Provider 패키지의 구성 요소는 기본적으로 상태를 생산/소비하는 영역으로 나뉜다
상태를 생산하는 영역을 Provider라고 하고, 소비하는 영역을 Consumer라고 한다
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return Provider<int>.value(
value: 0,
child: MaterialApp(
home: HomeScreen(...),
),
);
}
}
상태를 생산하는 Provider는 상태의 타입과 초기값을 위처럼 선언할 수 있다
그리고 child에 있는 위젯 내부에서 상태를 사용한다
앱 전역에서 접근하도록 하고 싶다면 MaterialApp()을 child에 넣으면 된다
return Consumer<int>(
builder: (context, data, child){
return Text(data.toString());
}
)
Consumer 위젯은 builder를 통해 상태 값(data)을 받아와 위젯을 빌드한다
이렇게 안에 선언된 위젯은 상태 값이 변화할 때마다 다시 빌드되어, 가급적 상태가 필요한 부분만 선언하여 불필요한 빌드를 막아야한다
int data = Provider.of<int>(context);
위와 같이 Consumer 위젯보다 좀 더 간단한 방법도 있다
여기까지는 그저 값을 전달할 뿐 실제로 상태의 변화를 다룰 수 없다
상태의 변화를 다루기 위해 ChangeNotifier와 ChangeNotifireProvider를 사용할 수 있다
ChangeNotifire는 변화를 알려주는 역할의 객체다
따라서 객체를 ChangeNotifire를 활용해 만들면 해당 객체 값의 변화를 감지 할 수 있다
이렇게 변화를 지속적으로 감시해 변화를 알 수 있는 것을 구독이라고 표현한다
class Counter{
int counter;
Counter(this.count);
void increment(){
count += 1;
}
void decrement(){
count -= 1;
}
}
int 타입의 Counter라는 클래스 형태로 만든 것이다
이렇게 작성하면 Counter의 count 값의 변화를 실시간으로 받아올 수 없다
이를 위해 ChangeNotifire를 사용한다
class Counter extends ChangeNotifire{
int counter;
Counter(this.count);
void increment(){
count += 1;
notifyListeners();
}
void decrement(){
count -= 1;
notifyListeners();
}
}
ChangeNotifire를 Counter 클래스에 상속하면 위처럼 변화를 구독할 수 있는 객체가 되어 notifyListeners()를 사용할 수 있게 된다
notifyListeners()를 통해 Counter의 값이 변화했음을 알려준다
이렇게 작성된 상태를 사용할 수 있는 위젯이 바로 ChangeNotifireProvider이다
ChangeNotifire가 추가되어 단순히 데이터를 제공해주던 Provider가 상태의 변화를 다룰 수 있게 된 것이다
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Counter(),
child: MaterialApp(...),
);
}
}
여기서 문제는 MaterialApp을 ChangeNotifireProvider 하나로만 감싸면 상태를 하나밖에 다루지 못한다
이룰 위해 Provider 패키지에서는 여러 개의 Provider를 사용할 수 있는 MultiProvider를 지원한다
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
Widget build(BuildContext context) {
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => State1()),
Provider(create: (context) => State2()),
],
child: MaterialApp(...),
);
}
}
요약
출처 : 쉽고 빠른 플러터 앱 개발