Riverpodとは?
Flutterで利用できる状態管理ライブラリの1つです。Flutterのライブラリの中でもよく使われており人気のあるライブラリです。Dartのみでも利用することができます。ちなみに、RiverpodはProviderのアナグラムになっています。
状態管理とは?
FlutterではデータやUIの状態をState機能を利用して管理しています。Riverpodではこの状態の管理や利用しやすくしてくれています。
主な構成要素
Riverpodで重要な役割を持つ以下の4つのことについてざっくり紹介します。
- プロバイダ
- ref (参照)
- Observer
- Scopes
Providers (プロパイダ)
プロパイダは、ステート(状態)を保管し監視することを可能にするオブジェクトです。ステートに変更があった時に通知してくれます。
final userProvider = FutureProvider.autoDispose.family<User, int>((ref, userId) async {
return fetchUser(userId);
});
ref (参照)
refはプロパイダの機能を利用するときに使うオブジェクトです。refを通じてプロパイダへアクセスすることができます。
@riverpod
class Counter extends _$Counter {
@override
int build() => 0;
void increment() {
// Counter can use the "ref" to read other providers
final repository = ref.read(userProvider);
userProvider.get('...');
}
}
ProviderScope (スコープ)
プロバイダーを管理するための空間を作ります。プロバイダーはこの空間で存在することができます。
@riverpod
String helloWorld(HelloWorldRef ref) {
return 'Hello world';
}
void main() {
runApp(
// ProviderScope を置くことで Riverpod が有効になる
ProviderScope(child: MyApp(),),
);
}
class MyApp extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final counter = useState(0);
final String value = ref.watch(helloWorldProvider);
// ...
}
}
ProviderObserver (オブザーバー)
同一スコープ内にあるプロバイダーの変更を検知することができる。下記の例は、オブザーバーでカウンターの値の変更を検知し、ログとして出力している。
class Logger extends ProviderObserver {
@override
void didUpdateProvider(
ProviderBase<Object?> provider,
Object? previousValue,
Object? newValue,
ProviderContainer container,
) {
print('''
{
"provider": "${provider.name ?? provider.runtimeType}",
"newValue": "$newValue"
}''');
}
}
void main() {
runApp(
// Logger インスタンスを observers のリストに追加する
ProviderScope(observers: [Logger()], child: const MyApp()),
);
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(home: Home());
}
}
final counterProvider = StateProvider((ref) => 0, name: 'counter');
class Home extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
// ボタン押下時などに、変更処理を加えるとオブザーバーで検知される
}
}
Providerとの違い
ProviderはRiverpod内で使われているコアパッケージの一つです。Providerで提供されている機能を、コード生成や特定の条件下で使いやすくしたものがRiverpodになります。
riverpod generatorとは?
Riverpodでは、アノテーションを利用することでプロバイダやオブザーバーの定義などを自動生成してくれるgeneratorという仕組みがあります。
仕組み
基本は、Providerの仕組みと同じでプロバイダで管理している値に変更があったら、各UIなどにBuildContextを通じて変更を通知する仕組みになっています。
使う場面
ウィジェット内で管理する状態が多くなったり、変化するロジックが複雑になったり、複数ウィジェット間で同一の状態を管理する必要が出てきた場合に、そのためのロジックを切り出すために利用することが多いです。
パッケージのインストール方法
下記のコマンドを使ってインストールすることができます。
$ flutter pub add riverpod
$ flutter pub get
使用の際の注意点
Riverpodのreadやwatch, listenなどはFlutterやWidgetのライフサイクルを考慮して設計されています。そのため「ref.read は build メソッドの中で使用する」といったライフサイクルを破壊するような使用を避けることが必要になります。