AsyncNotifierProviderのドキュメントがあんまりなかったのでまとめてみた
AsyncNotifierProviderのドキュメントがなかったので、まとめてみました
AsyncNotifierProviderはいつ使うProviderか
・データを取るのに非同期処理が必要(Async)
・データに変更があったらリアクティブに通知してほしい(Notifier)
ときに使えるProviderです。
全体像
こんな感じで書きます。List<Hoge>を提供するProviderの例になっています。
(例としてListを挙げているだけでListでない単一の値でもAsyncNotifierProviderを使うことはできます。)
class Hoge {
// 略
}
final hogeProvider = AsyncNotifierProvider<HogeNotifier, List<Hoge>>(
HogeNotifier.new,
);
class HogeNotifier extends AsyncNotifier<List<Hoge>> {
HogeNotifier() : super();
Future<List<Hoge>> build() async {
return await getHogeFromStorage();
}
Future<void> add(Hoge hoge) async {
update((p0) async {
state = const AsyncLoading();
p0.add(hoge);
await saveHogeToStorage(p0.map(toMap).toList());
return p0;
});
}
Future<void> remove(Hoge hoge) async {
update((p0) async {
state = const AsyncLoading();
p0.remove(hoge);
await saveHogeToStorage(p0.map(toMap).toList());
return p0;
});
}
}
詳細に
ここでProviderの定義をしています↓
final hogeProvider = AsyncNotifierProvider<HogeNotifier, List<Hoge>>(
HogeNotifier.new,
);
2つの型のうち最初のは後述するHogeNotifierクラスの型、2番目のはNotifierが実際に提供する値の型を設定します。
これがHogeNotifierです↓
class HogeNotifier extends AsyncNotifier<List<Hoge>> {
HogeNotifier() : super();
Future<List<Hoge>> build() async {
return await getHogeFromStorage();
}
Future<void> add(Hoge hoge) async {
update((p0) async {
state = const AsyncLoading();
p0.add(hoge);
await saveHogeToStorage(p0.map(toMap).toList());
return p0;
});
}
Future<void> remove(Hoge hoge) async {
update((p0) async {
state = const AsyncLoading();
p0.remove(hoge);
await saveHogeToStorage(p0.map(toMap).toList());
return p0;
});
}
}
ここで
・初期値を得る処理
・値を追加/削除/編集 etc...するときの処理
を書くことができます。
値を追加/削除するときの処理は(毎回書くのが面倒でないなら)なくてもいいです
buildの部分に初期値を得る処理を書きます
async/awaitで非同期的にできます
ここではadd()やremove()で追加/削除できるようにしましたが、この名前は別になんでも良いです
add()やremove()のなかではupdate()というメンバ関数を呼んでいて、これをやることで変更が通知されリアクティブにやってくれます(多分)
あとupdate()の中の関数で最初にstate = const AsyncLoading();
とやってやるとローディング状態も通知してくれるらしいです。
値を受け取る側
値を受け取る側では
ref.watch(hogeProvider).value
を読んでやることでよしなにやってくれます。
ロード中とかはnullになるっぽい
また、
ref.watch(hogeProvider).when(
data: data, // 通常時に表示するWidget
error: error, // エラー時に表示するWidget
loading: loading, // ロード中に表示するWidget
)
とすることでエラーやロード中の分岐もできるみたいです。
値を書き換える側
値を書き換える側では
ref.read(serversProvider.notifier).add(Hoge())
や
ref.read(serversProvider.notifier).remove(Hoge())
を呼ぶようにするとクラスのところで定義した関数を使えます。
(update()を生で使うことも可能です)
Discussion