【Riverpod学習】Providerの種類〜FutureProviderについて〜
以下の公式を読みながらFutureProviderについて勉強したのでその備忘録です
FutureProviderは、非同期処理を扱うためのRiverpodのプロバイダで、非同期コードの結果(Futureの結果)をアプリ内で管理するために使います。たとえば、ネットワークリクエストやデータベースからのデータ取得など、時間がかかる処理に適しています。これを使うことで、読み込み中やエラーの状態も簡単に扱えるため、非同期処理のUI表現がスムーズになります。
FutureProviderの概要
FutureProviderは、非同期処理(Future)を行い、その結果をUIで表示できるプロバイダです。通常のProviderは同期処理用ですが、FutureProviderは非同期処理の結果を待ってデータを提供します。
主な使用場面:
- ネットワークリクエストや、ファイル読み込みなどの非同期処理。
- エラー状態やローディング状態を簡単に管理する。
- データのキャッシュを行い、複数のウィジェットで同じデータを使う際にも効率的に扱える。
例: JSONファイルの読み込み
次の例では、FutureProviderを使って、アプリ内のJSONファイルを読み込み、設定(Configurationオブジェクト)を取得する非同期処理を行っています。
1. 非同期関数の定義
まず、@riverpodアノテーションを使って、非同期処理を行う関数を定義します。この関数はFutureを返すため、FutureProviderがそれを監視します。
Future<Configuration> fetchConfiguration(FetchConfigurationRef ref) async {
// assets/configurations.json からJSONファイルを読み込む
final content = json.decode(
await rootBundle.loadString('assets/configurations.json'),
) as Map<String, Object?>;
// Configurationクラスのインスタンスを返す
return Configuration.fromJson(content);
}
このコードでは、rootBundle.loadStringを使ってassets/configurations.jsonというファイルを読み込み、Configurationオブジェクトを作成しています。この操作は非同期的に行われ、完了するとFuture<Configuration>として返されます。
2. UIでの使用
次に、このFutureProviderの結果をUIで表示する方法を見ていきます。FutureProviderの結果はAsyncValueとして返されるため、エラー、読み込み中、データ取得完了の状態を簡単に管理できます。
Widget build(BuildContext context, WidgetRef ref) {
// fetchConfigurationProviderの状態を監視
final config = ref.watch(fetchConfigurationProvider);
// 状態に応じて異なるUIを表示
return switch (config) {
// エラーが発生した場合
AsyncError(:final error) => Text('Error: $error'),
// データが取得できた場合
AsyncData(:final value) => Text(value.host),
// データがまだ読み込まれていない場合
_ => const CircularProgressIndicator(),
};
}
ポイント:
- AsyncError: 非同期処理でエラーが発生した場合、そのエラー内容を表示。
- AsyncData: 非同期処理が成功し、データが取得できた場合、そのデータを使ってUIを更新。
- loading(_): 非同期処理がまだ完了していないときに、ローディングインジケーターを表示。
このように、AsyncValueを使うことで、非同期処理の3つの状態(エラー、データ、読み込み中)を簡単に扱えます。
3. FutureProviderの使いどころ
-
ネットワークリクエストや非同期ファイル読み込み
たとえば、APIからデータを取得したり、外部のリソース(ファイルなど)を読み込む際に便利です。FutureProviderは、非同期処理の結果をキャッシュし、複数のウィジェットで同じ結果を使う場合でも、データが無駄に再取得されることがありません。 -
非同期データのエラーハンドリングとローディング状態の表示
AsyncValueとして返されるため、非同期処理の結果が取得される前にローディングインジケーターを表示したり、エラーが発生したときにエラーメッセージを表示するのも簡単です。これは、ユーザーにとってスムーズなUI体験を提供するために非常に重要です。
4. FutureProviderとAsyncNotifierProviderの使い分け
FutureProvider
FutureProviderはユーザー操作による状態の変更はできません。たとえば、ネットワークから取得したデータを表示するだけなら適していますが、そのデータを元にさらにユーザー操作を反映させるのは難しいです。
使い方の例:
FutureProviderは、一度データを取得して、それを表示するだけのシンプルな非同期処理に向いています。
例: 設定ファイルやリモートAPIから一度データを読み込み、そのデータをアプリ内で表示する。データが変わることはない、もしくは頻繁には変わらない。
- 非同期処理で結果を取得するだけ(リクエスト後に操作が不要)。
- 状態を変更する必要がない(例えば、APIからデータを取得して一度だけ表示する場合)。
AsyncNotifierProvider
AsyncNotifierProviderは、FutureProviderのように非同期処理を扱うだけでなく、ユーザーの操作によって状態を変更できる 柔軟なプロバイダです。ユーザーがボタンを押したり、他のアクションを行った際に非同期処理を実行して、その結果に基づいて状態を更新します。
使い方の例:
AsyncNotifierProviderは、ユーザーのアクションに応じて非同期処理を開始し、その結果に応じて状態を更新する場面で使います。
例: タスク管理アプリで、リモートのサーバーからタスクリストを取得し、そのタスクに対して「完了」「未完了」を切り替える操作を行いたい場合。ユーザーがアクションを起こすたびに状態が変わるので、AsyncNotifierProviderの方が適しています。
- 非同期処理の結果を取得しつつ、ユーザー操作による状態変更が必要な場合(タスクの状態変更、リモートサーバーとのデータ同期など)。
- ユーザーの操作でデータの取得や更新を繰り返すような場合。
どちらを使うかは、非同期処理の結果を取得するだけでいいか(FutureProvider) 、それともユーザー操作に応じて状態を動的に変えたいか(AsyncNotifierProvider) で判断する
まとめ
- FutureProviderは、非同期処理(ネットワークリクエストやファイル読み込みなど)を管理し、その結果をAsyncValueで返します。
- 状態に応じたUIの表示(エラー、読み込み中、データ完了)が簡単に行えるため、非同期処理を扱う際に便利です。
- キャッシュ機能があり、複数のウィジェットが同じデータにアクセスする際に効率的にデータを再利用できます。
Discussion