
Riverpod은 Flutter에서 상태 관리를 보다 안전하고 효율적으로 할 수 있도록 도와주는 패키지로, 기존의 Provider 패키지를 개선하여 다양한 기능과 유연성을 제공합니다. 이를 통해 애플리케이션의 상태를 보다 쉽게 관리하고, 유지보수를 용이하게 합니다.
Provider의 개선판으로, 상태 관리의 편의성과 안전성을 높여줍니다. 전역 변수로 제공자를 선언하고, ProviderScope로 감싸 사용합니다.StatelessWidget과 유사하지만, Riverpod의 상태를 구독할 수 있는 기능을 제공합니다.ref.watch(): 상태를 구독하고, 상태가 변경될 때마다 빌드합니다.ref.read(): 상태를 읽기만 하고, 변경 사항을 구독하지 않습니다.NotifierProvider: 상태 변경을 알리는 Notifier 객체를 제공하는 Provider입니다.StateProvider: 간단한 상태를 관리하기 위한 Provider입니다.아래 예제는 간단한 카운터 앱을 통해 Riverpod의 사용 방법을 보여줍니다.
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
// 상태 제공자 선언
final counterProvider = StateProvider<int>((ref) => 0);
void main() {
runApp(
ProviderScope(
child: MyApp(),
),
);
}
class MyApp extends StatelessWidget {
Widget build(BuildContext context) {
return MaterialApp(
home: CounterApp(),
);
}
}
class CounterApp extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final counter = ref.watch(counterProvider).state;
return Scaffold(
appBar: AppBar(title: Text('Counter App')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('You have pushed the button this many times:'),
Text('$counter', style: Theme.of(context).textTheme.headline4),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
ref.read(counterProvider).state++;
},
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => A()),
ChangeNotifierProvider(create: (context) => B(a: context.read())),
],
child: MyApp(),
);
ProviderScope로 감싸면 의존성 순서에 상관없이 등록됩니다.final a = StateProvider<int>((ref) => 0);
final b = StateProvider<int>((ref) => ref.watch(a) * 2);
ProviderScope(
child: MyApp(),
);
MultiProvider(
providers: [
ChangeNotifierProvider(create: (context) => Counter()), // 1
ChangeNotifierProvider(create: (context) => Counter()), // 2
],
child: MyApp(),
);
Counter counter = context.read<Counter>(); // 2번만 접근 가능
final a = NotifierProvider<Counter, int>(() => Counter());
final b = NotifierProvider<Counter, int>(() => Counter());
Counter counter1 = ref.read(a.notifier);
Counter counter2 = ref.read(b.notifier);
BuildContext를 사용합니다.class MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
Counter counter = context.watch<Counter>();
return Text("${counter.count}");
}
}
WidgetRef를 별도로 만들어 사용합니다.class MyWidget extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
Counter counter = ref.watch(counterProvider);
return Text("${counter.count}");
}
}
Riverpod에서는 제공자를 전역 변수로 선언합니다. 이는 동일한 클래스를 여러 개 등록하고 사용할 수 있는 유연성을 제공하지만, 전역 변수가 늘어나게 되어 코드 관리가 어려워질 수 있습니다.
Riverpod은 Flutter의 BuildContext를 사용하지 않고 WidgetRef를 사용합니다. 이는 Flutter에 의존하지 않는다는 장점이 있지만, ConsumerWidget과 같은 위젯을 사용하기 위해 추가적인 코드가 필요하게 됩니다.
class MyWidget extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
Counter counter = ref.watch(counterProvider);
return Text("${counter.count}");
}
}
ref.watch는 필요한 경우에만 호출하여 불필요한 위젯 빌드를 최소화합니다.Riverpod와 같은 상태 관리 도구를 사용하는 것이 좋습니다.