Flutter ์ํ๊ด๋ฆฌ์์ Riverpod์ ์ค์ ์ฝ๋๋ฅผ ํตํด Riverpod์ ๊ณต๋ถํด๋ณด๊ฒ ์ต๋๋ค.
Riverpod์ ๊ตฌ์กฐ์ ์ ๊ทผ
Riverpod์ ์ํ ๊ด๋ฆฌ๋ฅผ ์ฌ๋ฌ ๋ ์ด์ด๋ก ๋ช ํํ ๋ถ๋ฆฌํฉ๋๋ค. ๊ฐ ์์๊ฐ ์ด๋ค ์ญํ ์ ํ๋์ง ์ดํด๋ณด๊ฒ ์ต๋๋ค.
1. ์ํ ํด๋์ค: ๋ฐ์ดํฐ ๊ตฌ์กฐ ์ ์
class CounterState {
int count = 0;
CounterState({required this.count});
}
์ด ์ ๊ทผ๋ฒ์ ์ฅ์ ์ ์ํ์ ๊ตฌ์กฐ๊ฐ ๋ช ํํด์ง๋ค๋ ์ ์ ๋๋ค. CounterState๋ง ๋ณด๋ฉด ์ด ๊ธฐ๋ฅ์ด ์ด๋ค ๋ฐ์ดํฐ๋ฅผ ๊ด๋ฆฌํ๋์ง ์ฆ์ ์ ์ ์์ด์.
2. Notifier: ๋ก์ง๊ณผ ์ํ ๋ณ๊ฒฝ
class RiverpodCounterNotifier extends Notifier<CounterState> {
// ๋ก์ง
void countUp() {
state = CounterState(count: state.count + 1);
print('RiverpodCounterNotifier - countUp count: ${state.count}');
}
void countDown() {
state = CounterState(count: state.count - 1);
print('RiverpodCounterNotifier - countDown count: ${state.count}');
}
@override
CounterState build() {
return CounterState(count: 0); // ์ด๊ธฐ ์ํ
}
}
ํต์ฌ ๋์ ์๋ฆฌ:
Notifier<CounterState> ์ ๋ค๋ฆญ
- ํ์ ์์ ์ฑ: state๋ ํญ์ CounterState ํ์
state ์ง์ ํ ๋น
state = CounterState(count: state.count + 1);
- ์ ์ธ์คํด์ค ์์ฑ: ๊ธฐ์กด ์ํ๋ฅผ ๋ณ๊ฒฝํ์ง ์๊ณ ์๋ก ์์ฑ
- ์๋ ์๋ฆผ: state ํ ๋น ์ ์๋์ผ๋ก UI์ ์๋ฆผ
- ์๋ ํธ์ถ ๋ถํ์: notifyListeners() ๊ฐ์ ๋ฉ์๋ ํธ์ถ ์์
build() ๋ฉ์๋
@override
CounterState build() {
return CounterState(count: 0); // ์ด๊ธฐ ์ํ ๋ช
์
}
- ์ด๊ธฐํ ๋ด๋น: Notifier๊ฐ ์ฒ์ ์์ฑ๋ ๋ ํธ์ถ
- ์ด๊ธฐ ์์์ : ์ด๊ธฐ ์ํ๊ฐ ์ด๋ป๊ฒ ์ค์ ๋๋์ง ๋ช ์์
3. Provider ์ ์: ํ์ ์์ ์ฑ
final riverpodCounterProvider = NotifierProvider<RiverpodCounterNotifier, CounterState>(() {
return RiverpodCounterNotifier();
});
Provider์ ๊ตฌ์กฐ ๋ถ์:
NotifierProvider<Notifier, State>
- ์ฒซ ๋ฒ์งธ ์ ๋ค๋ฆญ: RiverpodCounterNotifier (๋ก์ง ๋ด๋น)
- ๋ ๋ฒ์งธ ์ ๋ค๋ฆญ: CounterState (์ํ ํ์ )
- ํฉํ ๋ฆฌ ํจ์: () => RiverpodCounterNotifier() (์ธ์คํด์ค ์์ฑ)
4. ์ฑ ์ค์ : ProviderScope
void main() {
runApp(const ProviderScope(child: RiverpodCounterApp()));
}
ProviderScope์ ์ญํ :
- Riverpod ํ์ฑํ: ๋ชจ๋ Provider ๊ธฐ๋ฅ ์ฌ์ฉ ๊ฐ๋ฅ
- ์์กด์ฑ ์ปจํ ์ด๋: Provider๋ค์ ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ
- ๋ฃจํธ ์ค์ : ์ฑ ์ ์ฒด์์ Provider ์ ๊ทผ ๊ฐ๋ฅ
5. ConsumerWidget: ์ํ ๊ตฌ๋ ๊ณผ ์ฌ์ฉ
class RiverpodCounterHomePage extends ConsumerWidget {
RiverpodCounterHomePage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
return Scaffold(
appBar: AppBar(title: Text('RiverPod Counter App')),
body: SafeArea(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 10,
children: [
ConsumerCounterText(),
ElevatedButton(
onPressed: () {
ref.read(riverpodCounterProvider.notifier).countUp();
},
child: Text('์นด์ดํธ ์ฆ๊ฐ'),
),
ElevatedButton(
onPressed: () {
ref.read(riverpodCounterProvider.notifier).countDown();
},
child: Text('์นด์ดํธ ๊ฐ์'),
),
],
)
),
),
);
}
}
ConsumerWidget์ ํน์ง
StatelessWidget ๋์ ConsumerWidget:
- WidgetRef ref: ๋ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ก ref ์ ๊ณต
- Provider ์ ๊ทผ: ref๋ฅผ ํตํด ๋ชจ๋ Provider์ ์์ ํ๊ฒ ์ ๊ทผ
- ์๋ช ์ฃผ๊ธฐ ๊ด๋ฆฌ: ์์ ฏ์ด dispose๋ ๋ ์๋์ผ๋ก ์ ๋ฆฌ
ref.read()์ ์ฉ๋
ref.read(riverpodCounterProvider.notifier).countUp();
- ์ผํ์ฑ ์ ๊ทผ: ๋ฉ์๋ ํธ์ถ์ด๋ ์ด๋ฒคํธ ์ฒ๋ฆฌ์ฉ
- ๋ฆฌ๋น๋ ์์: ์ด ์ฝ๋๋ก ์ธํด ์์ ฏ์ด ๋ค์ ๋น๋๋์ง ์์
- notifier ์ ๊ทผ: .notifier๋ก Notifier ์ธ์คํด์ค์ ์ ๊ทผ
6. ์ํ ๊ตฌ๋ : ๋ณ๋ Consumer ์์ ฏ
class ConsumerCounterText extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return Text(
'Counter.count : ${ref.watch(riverpodCounterProvider).count}',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 30),
);
}
}
ref.watch()์ ํต์ฌ
ref.watch(riverpodCounterProvider).count
- ์ํ ๊ตฌ๋ : Provider์ ์ํ ๋ณํ๋ฅผ ๊ฐ์ง
- ์๋ ๋ฆฌ๋น๋: ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ด ์์ ฏ๋ง ๋ค์ ๋น๋
- ์ง์ ์ ๊ทผ: .count๋ก ์ํ ํ๋กํผํฐ์ ์ง์ ์ ๊ทผ
์์ ฏ ๋ถ๋ฆฌ์ ์ด์
- ์ฑ๋ฅ ์ต์ ํ: ์ํ๊ฐ ๋ณ๊ฒฝ๋์ด๋ ConsumerCounterText๋ง ๋ฆฌ๋น๋
- ์ฑ ์ ๋ถ๋ฆฌ: ๋ฒํผ๋ค์ ๋ฆฌ๋น๋๋์ง ์์
- ์ฌ์ฌ์ฉ์ฑ: ๋ค๋ฅธ ๊ณณ์์๋ ์ฝ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅ
ref์ ์ธ ๊ฐ์ง ํต์ฌ ๋ฉ์๋
Riverpod์์ ref๋ Provider์ ์ํธ์์ฉํ๋ ํต์ฌ ๋๊ตฌ์ ๋๋ค.
ref.watch() - ์ํ ๊ตฌ๋
final state = ref.watch(riverpodCounterProvider);
// ์ํ๊ฐ ๋ณ๊ฒฝ๋๋ฉด ์ด ์์ ฏ์ด ๋ฆฌ๋น๋๋จ
ref.read() - ์ผํ์ฑ ์ ๊ทผ
ref.read(riverpodCounterProvider.notifier).countUp();
// ๋ฉ์๋ ํธ์ถ๋ง, ๋ฆฌ๋น๋ ์์
์ ์ฒด ๋ฐ์ดํฐ ํ๋ฆ
ProviderScope
↓
riverpodCounterProvider (NotifierProvider)
↓
RiverpodCounterNotifier (๋ก์ง)
↓
CounterState (์ํ)
↓
ConsumerWidget (UI)
↓
ref.watch() (๊ตฌ๋
) / ref.read() (์ก์
)
๋์ ์๋๋ฆฌ์ค:
- ์ฌ์ฉ์๊ฐ ๋ฒํผ ํด๋ฆญ
- ref.read().countUp() ํธ์ถ
- Notifier๊ฐ ์๋ก์ด CounterState ์์ฑ
- state ํ ๋น์ผ๋ก ์๋ ์๋ฆผ
- ref.watch()๋ฅผ ์ฌ์ฉํ๋ ์์ ฏ๋ง ๋ฆฌ๋น๋
๋ง๋ฌด๋ฆฌ
Riverpod์ ๊ตฌ์กฐํ๋ ์ํ๊ด๋ฆฌ๋ฅผ ํตํด ์์ ํ๊ณ ์์ธก ๊ฐ๋ฅํ ์ฑ์ ๋ง๋ค ์ ์๊ฒ ํด์ค๋๋ค.
Riverpod์ ํต์ฌ ์์๋ค:
- CounterState: ๋ช ํํ ์ํ ๊ตฌ์กฐ
- Notifier<T>: ํ์ ์์ ํ ๋ก์ง ๊ด๋ฆฌ
- NotifierProvider: ์ปดํ์ผ ํ์ ๊ฒ์ฆ
- ConsumerWidget: ref๋ฅผ ํตํ ์์ ํ ์ ๊ทผ
- ref.watch/read: ๋ชฉ์ ์ ๋ง๋ ์ํ ์ฌ์ฉ
์ฝ๋๊ฐ ์ฒ์์๋ ๋ณต์กํด ๋ณด์์ง๋ง, ๊ฐ ์์์ ์ญํ ์ด ๋ช ํํ๊ณ ํ์ ์์คํ ์ ๋์์ ๋ฐ์ ์ ์์ด ์คํ๋ ค ๋ ์์ ํ๊ณ ํธ๋ฆฌํ์์ต๋๋ค.
'๐ฅ Bread Basics > Flutter' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Flutter] GetX ์ํ๊ด๋ฆฌ: ๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ (0) | 2025.06.27 |
---|---|
[Flutter] Provider ์ํ๊ด๋ฆฌ:: ChangeNotifier๋ฅผ ๋ ์ฒด๊ณ์ ์ผ๋ก (0) | 2025.06.27 |
[Flutter] MVVM ChangeNotifier:: (ํ๋ฉด) / (๋ฐ์ดํฐ, ๋ก์ง) ๋ฐ๋ก (1) | 2025.06.27 |
[Flutter] StatefulWidget:: ํ๋ฉด, ๋ฐ์ดํฐ, ๋ก์ง์ ํ ๋ฒ์ (0) | 2025.06.27 |
Dart ์ธ์ด ๊ธฐ๋ณธ๊ธฐ ๋ฐฐ์ฐ๊ธฐ (0) | 2025.04.28 |
mixin, sealed, base ํด๋์ค (0) | 2025.04.25 |
Record(ํํ), Destructuring (0) | 2025.04.25 |
Future, async, await, stream, listen, sink, yield (0) | 2025.04.25 |