Riverpod
: Flutter ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
Riverpod์ Flutter ๊ณต์ ์ํ๊ด๋ฆฌ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ Provider์ ๊ฐ์ ๋ ๋ฒ์ ์ผ๋ก, ๋ ์์ ํ๊ณ ๊ฐ๋ ฅํ ์ํ ๊ด๋ฆฌ๋ฅผ ์ ๊ณตํฉ๋๋ค.
Riverpod์ ์ฃผ์ ํน์ง
1.
์ ์ญ ์ํ ๊ด๋ฆฌ ๊ฐ๋ฅ
โข
Provider์ฒ๋ผ BuildContext๊ฐ ํ์ํ์ง ์์ โ ์ ์ญ์์ ์ํ ๊ด๋ฆฌ ๊ฐ๋ฅ
2.
์์ ํ ์ํ ๊ด๋ฆฌ
โข
StateNotifier๋ฅผ ์ฌ์ฉํด ๋ถ๋ณ ์ํ ๊ด๋ฆฌ ์ง์
โข
FutureProvider, StreamProvider๋ก ๋น๋๊ธฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ฐ๋ฅ
3.
์์กด์ฑ ์ฃผ์
(DI) ์ง์
โข
์ฌ๋ฌ Provider ๊ฐ ์์กด ๊ด๊ณ๋ฅผ ์ฝ๊ฒ ์ค์ ๊ฐ๋ฅ
4.
ref.watch, ref.read, ref.listen ํ์ฉ ๊ฐ๋ฅ
โข
ref.watch() โ ์ํ๊ฐ ๋ณ๊ฒฝ๋ ๋๋ง๋ค UI ์
๋ฐ์ดํธ
โข
ref.read() โ ์ํ ๊ฐ์ ์ฆ์ ๊ฐ์ ธ์ค์ง๋ง UI ๋ฆฌ๋ ๋๋ง ์์
โข
ref.listen() โ ํน์ ๊ฐ์ด ๋ณ๊ฒฝ๋ ๋ ์ฝ๋ฐฑ ์คํ
Riverpod ์ค์น
flutter pub add flutter_riverpod
Shell
๋ณต์ฌ
๋๋
dependencies:
flutter_riverpod: latest_version
YAML
๋ณต์ฌ
Riverpod ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
Provider ์ฌ์ฉํ๊ธฐ (๊ธฐ๋ณธ ์ํ ๊ด๋ฆฌ)
import 'package:flutter_riverpod/flutter_riverpod.dart';
// ์ํ๋ฅผ ๊ด๋ฆฌํ Provider ์ ์ธ
final counterProvider = StateProvider<int>((ref) => 0);
void main() {
runApp(ProviderScope(child: MyApp()));
}
class MyApp extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider); // ์ํ ๊ฐ์ง
return Scaffold(
appBar: AppBar(title: Text('Riverpod Example')),
body: Center(
child: Text('Count: $count', style: TextStyle(fontSize: 24)),
),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).state++, // ์ํ ์
๋ฐ์ดํธ
child: Icon(Icons.add),
),
);
}
}
Dart
๋ณต์ฌ
โข
StateProvider<int> โ ๊ธฐ๋ณธ์ ์ธ ์ํ ์ ๊ณต (์ด๊ธฐ๊ฐ 0)
โข
ref.watch(counterProvider) โ ์ํ ๋ณ๊ฒฝ ์ UI ์๋ ์
๋ฐ์ดํธ
โข
ref.read(counterProvider.notifier).state++ โ ๊ฐ ๋ณ๊ฒฝ
StateNotifierProvider ์ฌ์ฉํ๊ธฐ (๋ณต์กํ ์ํ ๊ด๋ฆฌ)
import 'package:flutter_riverpod/flutter_riverpod.dart';
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void increment() => state++;
}
// StateNotifierProvider ์ฌ์ฉ
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) => CounterNotifier());
class CounterScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
body: Center(child: Text('Count: $count')),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).increment(),
child: Icon(Icons.add),
),
);
}
}
Dart
๋ณต์ฌ
FutureProvider ์ฌ์ฉํ๊ธฐ (๋น๋๊ธฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ)
final futureProvider = FutureProvider<String>((ref) async {
await Future.delayed(Duration(seconds: 2)); // 2์ด ํ ๋ฐ์ดํฐ ๋ฐํ
return "Hello, Riverpod!";
});
class AsyncScreen extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final asyncValue = ref.watch(futureProvider);
return Scaffold(
body: Center(
child: asyncValue.when(
data: (data) => Text(data),
loading: () => CircularProgressIndicator(),
error: (err, stack) => Text('Error: $err'),
),
),
);
}
}
Dart
๋ณต์ฌ
GetX vs Bloc vs Provider vs Riverpod ๋น๊ต
๊ธฐ๋ฅ | GetX | Bloc | Provider | Riverpod |
์ํ ๊ด๋ฆฌ | ||||
๋น๋๊ธฐ ์ํ ๊ด๋ฆฌ | ||||
์์กด์ฑ ์ฃผ์
(DI) | ||||
๋ผ์ฐํ
๊ด๋ฆฌ | ||||
์ ์ญ ์ํ ๊ด๋ฆฌ | ||||
๋ฐ์ํ ํ๋ก๊ทธ๋๋ฐ ์ง์ | ||||
์ฝ๋ ๋ณต์ก๋ | ||||
์ฑ๋ฅ ์ต์ ํ | ||||
๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ | ||||
ํ
์คํธ ์ฉ์ด์ฑ | ||||
์ฑ ํฌ๊ธฐ ์ํฅ | ||||
Flutter ๊ณต์ ์ง์ | ||||
๋๊ท๋ชจ ์ฑ ์ ํฉ์ฑ |