
riverpodとは
Flutter開発における状態管理ライブラリです。
主に、グローバルな状態(アプリ全体で使うデータ)の管理に利用されます。
riverpod関連の用語
riverpodを利用する上で知っておいた方がいい用語を簡単に紹介します。
- 状態:アプリ内の変化するデータ。例えば、いいねのカウント数やログイン状態など。
- Notifier:状態を持ち、その状態を変化させることができる編集者みたいなもの。
- Provider:Notifierや状態にアクセスするための窓口みたいなもの。
import 'package:flutter_riverpod/flutter_riverpod.dart';
/// int型の状態(カウント)を管理する Notifier クラス
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0); // 初期値は 0
void increment() => state++; // カウントを +1
}
/// Notifier を使う Provider の定義
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});
- ref:Providerにアクセスするためのカギみたいなもの。StatelessWidgetやStatefulWidgetはrefを持つことができないので、Providerで囲まれた状態を監視したり変更したりできない。
- ref.watch:状態の変更を監視。状態が変更されたらUIを更新。
- ref.read:状態を変更(状態を一度だけ取得もできる)。
- ref.listen:状態の変更を監視。状態が変更されたら特定の処理を実行。
- ConsumerWidget:refを使うことでProviderの中の状態を知ることができるウィジェット。
// ConsumerWidgetのbuild関数内で定義
// watchで状態を監視
final count = ref.watch(counterProvider);
return Column(
children: [
Text('カウント: $count'), // ✅ ここが再描画される
// readで状態を変更
ElevatedButton(
onPressed: () {
ref.read(counterProvider.notifier).increment()
// watchしているのでcountを表示している部分が再描画される
},
child: Text('+1'),
),
],
);
riverpod_annotationとは
シンプルなコードを書くことで、NotifierやProviderを自動生成してくれる便利なパッケージです。
pubspec.yaml
riverpod_annotationを使う上で追加する必要のあるパッケージです。
dependencies:
flutter:
flutter_riverpod:
riverpod_annotation: # アノテーション(@で始まる特別な目印)の定義
dev_dependencies:
build_runner: # 生成処理を実行するツール
riverpod_generator: # @riverpod を使ったコードから .g.dart を自動生成する
実装:事前知識
- 同期処理(Future・Stream以外)の状態の場合はNotifier, NotifierProviderを生成
- 非同期処理(Future・Stream)の状態の場合は、AsyncNotifier, AsyncNotifierProviderを生成
- riverpod1系よりシンプルな構成になりました。
実装:同期処理
counter_provider.dart
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'counter_provider.g.dart'; // ファイル名.g.dartを作ってくれる
@riverpod
class Counter extends _$Counter {
@override
int build() => 0; // 初期値を返す
void increment() => state++; // 状態を+1
}
counter_provider.g.dart 生成コマンド
flutter pub run build_runner build --delete-conflicting-outputs
ConsumerWidgetでの使い方は同じです。
// ConsumerWidgetのbuild関数内で定義
// watchで状態を監視
final count = ref.watch(counterProvider);
return Column(
children: [
Text('カウント: $count'), // ✅ ここが再描画される
// readで状態を変更
ElevatedButton(
onPressed: () {
ref.read(counterProvider.notifier).increment()
// watchしているのでcountを表示している部分が再描画される
},
child: Text('+1'),
),
],
);
実装:非同期処理
user_name_provider.dart
import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'user_name_provider.g.dart';
@riverpod
class UserName extends _$UserName {
@override
Future<String> build() async {
await Future.delayed(const Duration(seconds: 1)); // 疑似API呼び出し
return 'John';
}
}
user_name_provider.g.dart 生成コマンド
flutter pub run build_runner build --delete-conflicting-outputs
ConsumerWidget 内
// ConsumerWidgetのbuild関数内で定義
// 状態を監視
final user = ref.watch(userNameProvider);
// 状態を3つのパターンに分けて表示
// data:状態を取得済
// loading:状態を取得中
// error:状態の取得に失敗(e:エラー内容, s:エラー発生箇所)
return user.when(
data: (name) => Text('こんにちは、$name'),
loading: () => CircularProgressIndicator(),
error: (e, s) => Text('エラー: $e'),
);
まとめ
- riverpod_annotation は、ProviderやNotifierの定義を簡潔に書くためのアノテーションパッケージです。
- @riverpod などのアノテーションを使うことで、状態管理のためのProviderやNotifierを自動生成できます。
- グローバルな状態だけでなく、非同期処理や引数付き(family)のProviderにも対応。
- 実際の自動生成は riverpod_generator + build_runner によって行われます。