FutureProvider - 単一の値を非同期的に作成する
FutureProvider = Provider + FutureBuilder とみなすことができます。
読み込み中 / エラー をハンドリングし、非同期処理が完了した時にWidgetを再構築させることが可能になります。
使用例としては、HTTPリクエストやファイルの読み取り、その他Futureを取り扱う処理全般で使用します。
Providerの宣言
以下は、プロジェクトの assets
ディレクトリ配下に置いた config.json
[1] ファイルを非同期で読み取り、
Map<String, Object?>
型に変換したものを提供するFutureProviderの例です。
final configProvider = FutureProvider<Map<String, Object?>>((ref) async {
final jsonString = await rootBundle.loadString('assets/config.json');
final content = json.decode(jsonString) as Map<String, Object?>;
return content;
})
Widgetからの利用
Widget build(BuildContext context, ScopedReader watch) {
// FutureProviderを読み取る(取得できる型は `AsyncValue<T>`)
final config = watch(configProvider);
return Scaffold(
// AsyncValue は `.when` を使ってハンドリングする
body: config.when(
// 非同期処理中は `loading` で指定したWidgetが表示される
loading: () => const CircularProgressIndicator(),
// エラーが発生した場合に表示されるWidgetを指定
error: (error, stack) => Text('Error: $error'),
// 非同期処理が完了すると、取得した `config` が `data` で使用できる
data: (config) {
return Text(config['host']);
}
),
);
}
loading
error
状態時のハンドリングが不要の場合は、 data?.value
を使って簡略化することもできます。
Widget build(BuildContext context, ScopedReader watch) {
// FutureProviderを読み取る(取得できる型は `AsyncValue<T>?`)
final config = watch(configProvider).data?.value;
return Scaffold(
// Nullチェックは必要になるが、記述は簡略化できる
body: Text(config?['host'] ?? 'loading...');
);
}
参考リンク
FutureProvider | Riverpodドキュメントページ
config.json
{
"appName": "SampleApp",
"isDebug": true,
"defaultAge": 20,
"defaultGenders": ["male", "female"]
}