🙆
[Flutter]FutureProviderとStreamProviderの個人的まとめ
注意:公式を見るのが一番ですのでそちらも見てください!
公式記事
参考記事
参考記事
FutureProvider
FutureProviderとは
である。
( 「断続的に」ではなく、「一回限り」 で非同期にデータを更新する)
使い所
- 非同期操作を実行し、そのデータを返り値にするとき。
- 非同期操作の error/loading ステートを適切に処理するとき。
- 非同期的に取得した複数の値を組み合わせて一つの値にするとき。
sample code(+Points)
ボタンを押下すると3秒後に「Hello World」を取得する簡単なアプリ
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
// ①ProviderScopeでラップする
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'FutureProvider',
theme: ThemeData(
textTheme: const TextTheme(bodyText2: TextStyle(fontSize: 50)),
),
home: HomePage(),
);
}
}
// ②FutureProviderの作成 (単一のデータを非同期で取得する)
final futureProvider = FutureProvider<dynamic>((ref) async {
await Future.delayed(const Duration(seconds: 3));
return 'Hello World';
});
// ③FutureProviderを作成すると「AsyncValue」オブジェクトを生成できる
//「AsyncValue」は非同期通信の通信中、通信終了、異常終了処理をハンドリングしてくれるRiverpodの便利な機能のこと
class HomePage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
// ③AsyncValueオブジェクトを取得する
final asyncValue = ref.watch(futureProvider);
return Scaffold(
appBar: AppBar(title: const Text('Hallo World')),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.refresh),
onPressed: () {
// ④押下すると状態を更新する処理
ref.refresh(futureProvider);
},
),
body: Center(
child: asyncValue.when(//⑤ AsyncValueの状態別に返り値を分岐指定する。
error: (err, _) => Text(err.toString()), //エラー時 => エラー文を出力
loading: () => const CircularProgressIndicator(), //読み込み時 => インジケータを表示
data: (data) => Text(data.toString()), //データ受け取り時 => データをString変換して表示
),
),
);
}
}
Points
- ①:ProviderScopeでルート(一番原始の)widgetをラップ
これにより変更を追える - ②:FutureProviderの定義。(設置。単一のデータを非同期で取得する)
futureProvider の中に、非同期で取得したい単一データを格納するようにした。 - ③:FutureProviderを作成すると「AsyncValue」オブジェクトを(returnとして)生成できる。非同期通信の通信中、通信終了、異常終了処理をハンドリングしてくれるRiverpodの便利な機能。
ref.watch(引数)
で(引数)の部分を監視(リッスン)して、変更があれば FutureProvider を監視した際の戻り値として返す。 - ④:この
ref.refresh(futureProvider)
メソッドにより(futureProvider の中の) StateController オブジェクトは再度生成される。状態を更新することになる。ボタンを押下することにより、オブジェクトを再生成し、状態更新するようにしている。 - ⑤:非同期処理ではAsyncValueを使用してローディング中またはエラーが発生した場合の値も返す必要があり、先ほど定義したfutureにwhenを使用してAsyncValueの状態別にコールバック関数で戻り値を指定する。
StreamProvider
StreamProviderとは
である。
sample code(+Points)
main.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
void main() {
// ProviderScopeでラップする
runApp(const ProviderScope(child: MyApp()));
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Count Down',
theme: ThemeData(
textTheme: const TextTheme(bodyText2: TextStyle(fontSize: 50)),
),
home: HomePage(),
);
}
}
// StreamProviderの作成 (データを非同期で断続的に取得する)
final streamProvider = StreamProvider<dynamic>((ref) {
Stream<dynamic> getNumbers() async* {
await Future.delayed(const Duration(seconds: 1));
yield 'Are You Ready?';
await Future.delayed(const Duration(seconds: 1));
yield 3;
await Future.delayed(const Duration(seconds: 1));
yield 2;
await Future.delayed(const Duration(seconds: 1));
yield 1;
await Future.delayed(const Duration(seconds: 1));
yield '';
}
return getNumbers();
});
// StreamProviderを作成すると「AsyncValue」オブジェクトを生成できる
//「AsyncValue」は非同期通信の通信中、通信終了、異常終了処理をハンドリングしてくれるRiverpodの便利な機能のこと
class HomePage extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
// AsyncValueオブジェクトを取得する
final asyncValue = ref.watch(streamProvider);
return Scaffold(
appBar: AppBar(title: const Text('Count Down')),
floatingActionButton: FloatingActionButton(
child: const Icon(Icons.refresh),
onPressed: () {
// 状態を更新する
ref.refresh(streamProvider);
},
),
body: Center(
child: asyncValue.when(
error: (err, _) => Text(err.toString()), //エラー時
loading: () => const CircularProgressIndicator(), //読み込み時
data: (data) => Text(data.toString()), //データ受け取り時
),
),
);
Points
-
final streamProvider = StreamProvider
でStreamBuilderを定義。
FutureProviderr と StreamProviderの違い
- FutureProvider:「単一のデータ取得」に使う
- StreamProvider:「断続的なデータ取得」に使う
まあFutureとStreamの違いも単一の変数を扱うとき・Listみたいに複数データを扱うときって違いだから、この違いも普通な感じもする。
次はFutureとStreamの違いについて調べよ〜
まだまだ全然理解していないですが、今回は以上です。間違えが見つかり次第、或いは知識がアップデートされ次第改訂していきます。🙏
Discussion