筆者はまだまだflutter学習中のため間違った情報が記載されている可能性もあります。予めご了承ください。間違い、改善点等あればお手柔らかに教えていただけるとありがたいです。
この記事で得られる知識
Futureなどの非同期処理後に、リビルドされる前にその結果を取得し画面に反映する方法。なお、この記事のコードはサンプルのためそのままでは動きません。
対策1 Flutter Hooksを使用して変更の完了を通知して、データを再取得させるようにする
Flutter HooksのuseEffectの第2引数に変更を知らせる変数を渡しておき、再取得させたいタイミングで通知させます。通知を受け取ると再度データを取得してくれます。
final sampleChange = ref.watch(sampleChangeProvider)
useEffect(
() {
newData = repository.getData();
return null;
},
[sampleChange],
);
class SampleChangeNotifier extends StateNotifier<bool> {
SampleChangeNotifier() : super(false);
void notifyChange() {
state = !state;
}
}
final sampleChangeProvider = StateNotifierProvider<SampleChangeNotifier, bool>(
(ref) => SampleChangeNotifier(),
);
対策2 RiverpodのonDispose関数を利用する
データの変更が終了すれば、dbProviderを一旦破棄します。すると、dbProviderを監視していたproviderも更新され、データを再度取得できるという方法です。
final sampleProvider = //データ取得のためのprovider
FutureProvider.family.autoDispose<bool, DateTime>((ref, date) async {
final datebase = ref.watch(dbProvider); //ここでdatabaseの変更を監視している
final response = await datebase.getData();
return response;
});
ref.invalidate(dbProvider); //データを変更した処理のあとにdbProviderを一旦破棄
final dbProvider = Provider<SampleDatabase>(
(ref) {
final database = SampleDatabase();
ref.onDispose(() async { //onDispose関数を使ってref.invalidateされた際の処理を記載
await database.close(); //ここでdatabaseのインスタンスをcloseしておかないとメモリーリークにとなることがある
});
return database;
},
);
最後に
いかがだったでしょうか。この記事が誰かの役に立てば嬉しいです。ちなみに筆者は、databaseのインスタンスをcloseしてなくて「LateInitializationError」となるエラーに苦しめられました(笑)
そのため、機能を実現する別の方法を探して(対策1)、ヒントをもらって再度取り組んでみた(対策2)というのが今回の記事の背景です。読んでいただきありがとうございました!