やりたいこと
画面表示時にAPIを介して値を取得し、画面表示したい。
refを使って他のプロバイダのstateを変更したい。 ⇦ これが厄介だった
問題
・ConsumerWidgetにはiOSの様にviewDidLoadなどの細かいlifecycleが提供されていない
・viewModelProviderを生成する時に下記のエラーが出る(プロバイダーの生成中に他のプロバイダーの値は変えちゃダメだよ的なやつ)
Providers are not allowed to modify other providers during their initialization.
簡単な方法
- viewModelの生成時にコンストラクタで値取得を行う
→ refを通して他のプロバイダーのstateを変更しようとするとcrashする。(変更しないのであれば問題ない) - FutureProviderを使う
→ loadingやerrorなどの処理を個別に書いたりしないといけないので少し面倒。今回のMVVMに合わせて実装をするのが難しくなる - Consumerを重ねる → これを解説します
コード
HogePage
class HogePage extends ConsumerWidget {
const HogePage({
Key? key,
}) : super(key:key);
@override
Widget build(BuildContext context, WidgetRef ref) {
final provider = hogeViewModelProvider;
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
ref.read(provider.notifier).initialize();
});
return Consumer(
builder: (_, widgetRef, __) {
final state = widgetRef.watch(provider);
}
}
}
}
HogeViewModel
final hogeViewModelProvider = StateNotifierProvider.autoDispose<bool>((ref) {
return HogeViewModel(false, reader: ref.read);
});
class HogeViewModel extends StateNotifier<bool> {
HogeViewModel(bool state, { required this.reader }) : super(state);
final Reader reader;
void initialize() {
// ここに画面表示時の処理を記載する
}
}