Flutter Provider
Provider란?
Flutter 앱에서 여러 위젯 간에 데이터를 공유하고, 상태 변경을 효율적으로 관리할 수 있게 해주는 패키지가 바로 Provider입니다.
Provider는 Flutter 공식 팀에서 권장하는 상태 관리 솔루션으로, ChangeNotifier를 활용한 간단하면서도 강력한 상태 관리 방식을 제공합니다. MVVM 패턴 구현에 필수적이며, 의존성 주입과 상태 공유를 깔끔하게 처리할 수 있습니다.
Provider는 Flutter의 상태 관리 패키지로, InheritedWidget을 기반으로 만들어졌습니다. 복잡한 InheritedWidget의 사용을 단순화하고, ChangeNotifier와 결합하여 반응형 상태 관리를 가능하게 합니다.
주요 특징
- 직관적이고 사용하기 쉬운 API를 제공합니다.
- 필요한 위젯만 리빌드하여 성능 최적화를 진행합니다.
- 깔끔한 의존성 주입 패턴을 지원합니다.
- Mock 객체를 쉽게 주입하여 테스트 용이성을 높입니다.
- Flutter 공식에서 권장하는 상태 관리 솔루션입니다.
왜 Provider를 사용하는가?
1. 기존 방식의 문제점
// 기존 방식: StatefulWidget의 한계
class CounterWidget extends StatefulWidget {
@override
_CounterWidgetState createState() => _CounterWidgetState();
}
class _CounterWidgetState extends State<CounterWidget> {
int _counter = 0;
void _increment() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Column(
children: [
Text('Count: $_counter'),
ElevatedButton(
onPressed: _increment,
child: Text('Increment'),
),
],
);
}
}
이 방식의 문제점:
- 상태를 여러 위젯에서 공유하기 어려움
- 깊은 위젯 트리에서 상태 전달이 복잡함
- 불필요한 위젯 리빌드 발생
Provider는 기존 방식의 문제점을 해결해줍니다.
- 앱 전체에서 상태를 쉽게 공유할 수 있음
- 변경된 부분만 리빌드 가능
- 테스트와 유지보수가 쉬움
기본 사용법
1. 패키지 설치
pubspec.yaml 파일에 provider 패키지를 추가합니다:
dependencies:
flutter:
sdk: flutter
provider: ^6.1.5+1
2. ChangeNotifier 생성
상태를 관리할 클래스를 생성하고 ChangeNotifier를 상속받습니다:
import 'package:flutter/foundation.dart';
class Counter extends ChangeNotifier {
int _count = 0;
int get count => _count;
void increment() {
_count++;
notifyListeners(); // 상태 변경을 알림
}
void decrement() {
_count--;
notifyListeners();
}
}
3. Provider 등록
main.dart에서 앱의 최상위에 Provider를 등록합니다:
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'counter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ChangeNotifierProvider(
create: (context) => Counter(),
child: MaterialApp(
title: 'Provider 예제',
home: HomePage(),
),
);
}
}
4. Provider 사용
위젯에서 Provider를 사용하여 상태에 접근합니다:
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Provider 예제'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Consumer를 사용하여 상태 구독
Consumer<Counter>(
builder: (context, counter, child) {
return Text(
'Count: ${counter.count}',
style: TextStyle(fontSize: 24),
);
},
),
SizedBox(height: 20),
ElevatedButton(
onPressed: () {
// Provider를 통해 상태 변경
Provider.of<Counter>(context, listen: false).increment();
},
child: Text('Increment'),
),
ElevatedButton(
onPressed: () {
Provider.of<Counter>(context, listen: false).decrement();
},
child: Text('Decrement'),
),
],
),
),
);
}
}