LoginSignup
1
1

flutter 非同期処理をほぼ同期的に画面に反映する方法

Last updated at Posted at 2024-03-11

筆者はまだまだ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)というのが今回の記事の背景です。読んでいただきありがとうございました!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1