宣言型プログラミング
Stateless ウィジェットのようにビジネスロジックを記述できます。
ネットワークリクエストは必要に応じて自動的に再計算され、ロジックの再利用・合成・保守が容易になります。
共通のUIパターンを簡単に実装
Riverpodを使えば、入力しながら検索/引っ張って更新のような複雑なUIパターンでも、数行のコードで実装できます。
開発ツールに対応
Riverpodはよくあるミスをコンパイルエラーとして扱い、コンパイラを強化します。カスタムlintルールやリファクタリングオプションも提供します。ドキュメント生成用のコマンドラインまで備えています。
特徴
- ✅ 宣言型プログラミング
- ✅ ネイティブネットワークリクエストに対応
- ✅ ロード/エラーの自動ハンドリング
- ✅ コンパイル時の安全性
- ✅ 型安全なクエリパラメータ
- ✅ テスト対応可
- ✅ バニラDartで動作 (サーバー/CLI/...)
- ✅ 組み合わせやすいステート
- ✅ 引っ張って更新の動作に標準でサポート
- ✅ カスタムlintルール
- ✅ リファクタリング標準搭載
- ✅ ホットリロードのサポート
- ✅ ロギング
- ✅ WebSocketサポート
- ✅ ドキュメント生成
どこからでも共有ステートを宣言
main.dart と UI 側のコードの間を行き来する必要はありません。
共有ステートは、独立したパッケージや、利用するWidgetの近くなど、適切な場所に配置でき、テストのしやすさも維持されます。
// A shared state that can be accessed by multiple widgets at the same time.
class Count extends _$Count {
int build() => 0;
void increment() => state++;
}
// Consumes the shared state and rebuild when it changes
class Title extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(countProvider);
return Text('$count');
}
}
ステートの再計算、UI の更新を最小限に
build メソッドの中でリストをソート / フィルタする必要はありません。高度なキャッシュ手法に頼る必要もありません。
Provider と "families" を使って、本当に必要な時に限り、リストのソートや HTTP リクエストを実行できます。
List<Todo> filteredTodos(Ref ref) {
// Providers can consume other providers using the "ref" object.
// With ref.watch, providers will automatically update if the watched values changes.
final List<Todo> todos = ref.watch(todosProvider);
final Filter filter = ref.watch(filterProvider);
switch (filter) {
case Filter.all:
return todos;
case Filter.completed:
return todos.where((todo) => todo.completed).toList();
case Filter.uncompleted:
return todos.where((todo) => !todo.completed).toList();
}
}
リファクターで日々の作業を簡略化
Riverpod は、"Wrap widget in a Consumer"、のような、様々なリファクターを提供しています。リファクタリング一覧

lintルールでコードの保守性を保つ
Riverpodに特化した新しいlintルールは実装済みであり、今後さらに継続的に追加されます。これにより、コードが最適な状態に保たれます。lintルール一覧

プロバイダの安全な読み取り
プロバイダを読み取った結果、bad stateになることは決してありません。プロバイダを読み取るために必要なコードを書ければ、常に有効な値を取得できます。
これは非同期により値を取得する場合も同様に適用されます。Providerとは対照的に、Riverpodは読み込み/エラーケースのハンドリングを明確に処理できます。
Future<Configuration> configurations(Ref ref) async {
final uri = Uri.parse('configs.json');
final rawJson = await File.fromUri(uri).readAsString();
return Configuration.fromJson(json.decode(rawJson));
}
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final configs = ref.watch(configurationsProvider);
// Use pattern matching to safely handle loading/error states
return switch (configs) {
AsyncData(:final value) => Text('data: ${value.host}'),
AsyncError(:final error) => Text('error: $error'),
_ => const CircularProgressIndicator(),
};
}
}
DevTools によるステートの検証
Riverpodを使うと、FlutterのDevToolsでステートが可視化されます。
加えて、より本格的なステート検証ツールの開発が進行中です。
