StateNotifierProviderはasyncを使えない…
StateNotifierの初期値にDBや内部ストレージから非同期で取得した値をセットしたい!
というケースは多々あると思います。
class FormItemList extends StateNotifier<List<Item>> {
FormItemList(List<Item> initialState) : super(initialState);
void set({required List<Item> itemList}) {
state = itemList;
}
Future<List<Item>> addNewItem({
required List<Item> itemList,
}) async {
state = [...state, ...itemList];
return state;
}
}
このようなStateNoriferをproviderで提供するとします。
非同期関数で取得した値を初期値として渡してあげる場合、以下のように書きたくなりますが、StateNotifierProviderの初期化メソッド内ではasync/awaitを使用できません。
final formItemProvider = StateNotifierProvider<FormItemList, List<Item>>((ref) async{
// NG
await initialItem = ref.watch(hogeProvider).fetch();
return FormItemList(initialItem);
});
これと同様のことを実現するには、まずStateNotifierに初期化用のメソッドを用意してあげます。
class FormItemList extends StateNotifier<List<Item>> {
FormItemList(List<Item> initialState) : super(initialState);
//初期化メソッドを追加
Future<void> initialize({required Ref ref}) async {
// ここで非同期処理を行う
final List<Item> initialItem = await ref.watch(hogeProvider).fetch();
state = initialItem
}
// 以下略
}
StateNotifierProviderの初期化時にこのメソッドを呼んであげればOKです
final formItemProvider = StateNotifierProvider<FormItemList, List<Item>>((ref) {
//空のリストでインスタンスを作成
final notifier = FormItemList([]);
//初期化メソッドを呼び出す
notifier.initialize(ref: ref);
return notifier;
});
このように記述することでformItemProviderの初回呼び出し時に、非同期で取得した初期値をセットしたStateNotifierを提供することができます。
当たり前といえば当たり前な方法ですね!