🤯

AsyncNotifierProviderのドキュメントがあんまりなかったのでまとめてみた

2024/03/03に公開

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