Riverpod — Flutterのためのコンパイル済み状態および依存関係マネージャーで、2021年にRemi RousseletがProviderの後継として作成しました。RiverpodはProviderの根本的な問題を解決します:コンパイル時チェックの欠如、BuildContextへの依存、ProviderNotFoundExceptionの複雑さ。pub.devによると、このパッケージは5000以上のいいねを獲得し、新しいプロジェクトでProviderを積極的に置き換えています。
重要なポイント
Riverpodは、プロバイダーの記述を安全なDartコードにコンパイルする、Flutter向けの状態管理および依存関係注入ライブラリです。Providerとは異なり、RiverpodのプロバイダーはBuildContextに縛られません:グローバルまたはProviderScope内で作成され、どこからでもアクセス可能です。コンパイラはビルド時に型、依存関係、プロバイダーグラフの整合性をチェックし、ProviderNotFoundExceptionのような実行時エラーを排除します。
Riverpodはテストにoverrideモデルを使用します:各プロバイダーは、サブクラスを作成したりインターフェースをモックしたりせずに、ProviderScope.overrideWithを介してオーバーライドできます。これによりテストが分離されます:各テストは完全に制御された依存関係グラフの独自のコピーを取得します。
Flutter Community Survey 2025によると、RiverpodはProviderとBLoCに次いで人気で第3位です。しかし、Riverpodは最も急速に成長しているパッケージです:2024年に+120%のインストール増。主な理由:コンパイル時の安全性、ProviderNotFoundExceptionの不在、AsyncValueによる組み込み非同期サポート。
Riverpodは8種類のプロバイダーを提供し、それぞれ特定のシナリオに対応します:Provider(定数/サービス)、StateProvider(プリミティブ状態)、StateNotifierProvider(StateNotifierを使用した複雑なロジック)、ChangeNotifierProvider(Providerからの移行用)、FutureProvider(非同期データ、1回限り)、StreamProvider(リアクティブストリーム)、NotifierProvider(新しいAPI、Flutter 3.10+)、AsyncNotifierProvider(非同期Notifier)。
final counterProvider = StateNotifierProvider<CounterNotifier, int>((ref) {
return CounterNotifier();
});
class CounterNotifier extends StateNotifier<int> {
CounterNotifier() : super(0);
void increment() => state++;
void decrement() => state--;
}
class CounterScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Text('$count');
}
}ProviderRef — 他のプロバイダーにアクセスするために各プロバイダーに渡されるオブジェクト。ref.watch — 変更の購読、ref.read — 1回限りの読み取り、ref.invalidate — キャッシュのリセット。ProviderRefはProviderのBuildContextを置き換えます:任意のプロバイダーがウィジェットツリーにアクセスせずに他のプロバイダーを読み取れます。これによりUIレイヤーの外部で依存関係グラフを構築できます。
ProviderScope — Riverpodが機能するために必須のルートウィジェット。ProviderScopeはすべてのプロバイダーを保存し、それらのライフサイクルを管理し、値をキャッシュします。ProviderScopeがないと、アプリはProviderNotFoundExceptionでクラッシュします。ProviderScopeはネスト可能で、ネストされたスコープは親プロバイダーをオーバーライドし、テストや機能の分離に使用されます。
AsyncValue — 非同期状態を表現するためのRiverpodのシールドクラス。AsyncValueには3つのバリアントがあります:AsyncData(成功データ)、AsyncError(エラー)、AsyncLoading(ローディング)。loading/error/dataを手動で切り替える代わりに、各FutureProviderまたはStreamProviderが自動的にAsyncValueを返し、ウィジェットがref.watchを介して3つの状態すべてを処理します。
final userProvider = FutureProvider((ref) async {
final api = ref.watch(apiProvider);
return await api.fetchUser();
});
class UserScreen extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final userAsync = ref.watch(userProvider);
return userAsync.when(
data: (user) => UserWidget(user),
error: (e, _) => ErrorWidget(e.toString()),
loading: () => CircularProgressIndicator(),
);
}
}AsyncValue.when — 3つの状態すべてをパターンマッチングするメソッド。コンパイラは3つのケースすべてが処理されていることを確認します — loadingまたはerrorを忘れると、コードはコンパイルされません。AsyncValue.whenData — データのみ(loading/errorが必要ない場合)。AsyncValue.guard — 例外をAsyncErrorに変換するためのtry-catchのラッパー。keepAlive — プロバイダーキャッシュがスコープ外に出たときに破棄されるのを防ぐフラグ。
コード生成 — Riverpod 2.0+の主要機能。関数に@riverpodアノテーションを付けると、正しい型、リファクタリングサポート、オートコンプリートを備えたプロバイダーが自動生成されます。コード生成はriverpod_generatorとbuild_runnerを使用します。開発者が純粋関数を書くと、型、クラス、ファクトリコンストラクタなど、残りのすべてが自動生成されます。
@riverpod
String helloWorld(HelloWorldRef ref) {
return 'Hello World';
}
// 生成: final helloWorldProvider = Provider((ref) => 'Hello World');
@riverpod
class Counter extends _$Counter {
int build() => 0;
void increment() => state++;
}Notifier — コード生成を伴うミュータブル状態の新しいAPI。Notifierはbuild()メソッドと状態変更メソッドを持つクラスです。StateNotifierとは異なり、Notifierは別の状態クラスを必要とせず、getter/setterを介してstateに直接アクセスできます。Riverpodは@riverpodでアノテーションされた各Notifierクラスに対してNotifierProviderを自動生成します。
build_runner: コード生成はdart run build_runner buildコマンドで実行されます。生成されたファイルには.g.dartサフィックスが付き、ソースコードにインポートされます。アノテーションやプロバイダーの型が変更された場合、コード生成を再実行する必要があります。Riverpod 2.xはすべての新規プロジェクトにコード生成を推奨しています — 手動のプロバイダー作成は非推奨になりつつあります。
主な違い RiverpodとProviderの間:BuildContextからの独立性、コンパイル時の安全性、組み込みの非同期サポート、自動キャッシング、overrideによるテスト。Providerは状態にアクセスするためにBuildContextを必要とします(context.watch、context.read)、RiverpodはWidgetRefとグローバルに宣言されたプロバイダーを使用します。
| 特性 | Provider | Riverpod |
|---|---|---|
| BuildContext依存 | あり | なし |
| コンパイル時チェック | なし | あり(@riverpod経由) |
| ProviderNotFoundException | 実行時 | 不可能 |
| 非同期 | 手動 | AsyncValue(組み込み) |
| テスト | Providerのラッパー | ProviderScope.overrideWith |
| キャッシング | なし | 自動 + keepAlive |
Providerからの移行: Riverpodは、書き換えなしで既存のChangeNotifierを使用するためのChangeNotifierProvider.adaptiveをサポートしています。段階的移行:最初に新機能をRiverpodで書き、次に古いProviderインスタンスをアダプターを介してRiverpodプロバイダーに置き換えます。両方のパッケージが1つのプロジェクトで共存できるため、開発を凍結せずに移行できます。
RiverpodのテストはProviderScope.overrideWithに基づいています。各プロバイダーは、モックやDIコンテナなしでテスト用ProviderScope内でオーバーライドされます。ProviderContainer — Flutterなしのテスト用の分離環境(純粋なDart)、ウィジェットレンダリングなしでプロバイダーをテストできます。
import 'package:flutter_test/flutter_test.dart';
import 'package:riverpod/riverpod.dart';
void main() {
test('Counter increments correctly', () {
final container = ProviderContainer();
container.read(counterProvider.notifier).increment();
expect(container.read(counterProvider), 1);
});
testWidgets('UI updates on increment', (tester) async {
await tester.pumpWidget(
ProviderScope(
overrides: [counterProvider.overrideWithValue(5)],
child: CounterScreen(),
),
);
expect(find.text('5'), findsOneWidget);
});
}ProviderContainer — Flutterなし。ウィジェットなしでプロバイダーのユニットテストにはProviderContainerを使用します。overrideWithValue — 特定の値でプロバイダーを置き換える。overrideWith — プロバイダーファクトリで置き換える(サービスのモック用)。autodispose — テストでは、container.dispose()を使用してプロバイダーがスコープ外に出たときに破棄されることを確認します。
よくある質問
Riverpodは、グローバルプロバイダー、AsyncValue、コード生成を備えた状態管理ライブラリです。BLoCは、Event → Stream → Stateのアーキテクチャパターンです。Riverpodは学習が容易で、@riverpodアノテーションによる優れたDXを提供します。BLoCは厳格なビジネスロジックの分離とBlocObserverによるイベントトレーシングを提供します。選択はプロジェクトのパラダイムに依存します:RiverpodはProviderに近く、BLoCはリアクティブストリームに近いです。
Autodisposeは、誰も購読していないプロバイダーを自動的に破棄するメカニズムです。デフォルトでは、すべてのRiverpodプロバイダーはautodisposeします:ウィジェットがツリーを離れると、プロバイダーはメモリから削除されます。keepAlive — 常に生き続けるべきプロバイダー(APIクライアント、リポジトリ、設定)のautodisposeを無効にするフラグ。これによりメモリリークが防止されます — 未使用のプロバイダーは自動的に破棄されます。
ref.invalidate — プロバイダーキャッシュを強制的にリセットするメソッド。invalidate後、次回の読み取り時にプロバイダーが再作成されます:FutureProviderは非同期関数を再実行し、StreamProviderはストリームに再購読します。データ更新を強制するにはinvalidateを使用します(プルツーリフレッシュ、ユーザー切り替え)。ref.refresh — invalidate + 読み取りの組み合わせ:1回の操作でリセットしてすぐに新しい値を読み取ります。
はい。Riverpod 1.xはコード生成なしでのみ動作します — プロバイダーはProvider()、StateNotifierProvider()、FutureProvider()などを使用して手動で作成されます。Riverpod 2.xは両方のアプローチをサポートしています。コード生成なしではボイラープレートが増えますが、build_runnerやdart run build_runner buildへの依存はありません。小規模プロジェクト(30プロバイダーまで)では手動作成が妥当ですが、大規模プロジェクトではコード生成が必須です。
Family — 外部パラメータを受け入れるプロバイダーモディファイア。例えば、userProvider(123) — ID 123のユーザーをロードするプロバイダー。Familyプロバイダーは一意のパラメータごとに個別に結果をキャッシュします。各アイテムがIDでロードされるアイテムのリストにはFamilyを使用します。Familyモディファイアはすべてのプロバイダータイプで利用可能です:Provider.family、FutureProvider.family、StreamProvider.family。
まとめ
ターンキー方式のモバイルアプリケーションを開発します
IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。