本文へスキップ
Hironobu Iga

Riverpod の Provider のキャッシュをログアウト時に効率的に削除する

ログアウト時に値を変更する Provider を 1 つ用意し、各 Provider の初期化でそれを watch させることで、消し忘れを構造的に防ぐ方法です。

公開日

この記事は別サイトにも掲載しています。 https://iganin.hatenablog.com/entry/2021/09/02/233939

TL;DR;

  • logout 時に値を変更する Provider を作成して、各 Provider の初期化処理でその Provider を watch する

環境

[✓] Flutter (Channel stable, 2.2.3, on macOS 11.3.1 20E241 darwin-x64, locale ja-JP)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] IntelliJ IDEA Ultimate Edition (version 2021.1.2)
[✓] VS Code (version 1.59.1)

hooks_riverpod: 0.14.0+4

モチベーション

セキュリティ上ログアウト時はローカルのデータを削除したい。

たとえば、ログアウトして別のアカウントでログインし直した場合に別アカウントのデータが残っているとする。 画面上に別アカウントのデータが表示されるのは当然いやだが、ポストなどのリクエストに別アカウントのデータがのってしまい、バックエンドのデータに別アカウントのデータが混ざってしまうとまずい。

そのため、ログアウト時はローカルの DB キャッシュやインメモリキャッシュは削除しておきたい。 以下で Riverpod の provider のキャッシュを効率的に削除する方法を考える。

Riverpod のキャッシュを削除する

愚直に考えると、ChangeNotifierProvider や StateNotifierProvider であれば clear メソッドなどを生やして、データを初期化して、StateNotifier などであれば初期値をいれるというのを思いつく。

ただ、都度都度メソッドを書くのはめんどくさいし、プロパティの追加時などに clear メソッドに書き忘れるなどが起こりそうである。

一つの方法としては、logout 時に値を書き換える provider を作成しておいて、各 provider の初期化時にその provider を watch するという方法がある。

final logoutProvider = StateProvider<DateTime?>((ref) => null);


final sampleProvider = StateProvider<String?>((ref) {
  ref.watch(logoutProvider);
  return null;
});

今回は簡単のために logout 日時を値として持つような provider にした。ログイン中のユーザー情報にするなど色々方法はあると思う。 こうすると、logoutProvider の state に新しい値が入ったタイミングで sampleProvider の初期化が走り現在の値が破棄される。

この方法の嬉しい点は、特別な考慮をせずとも初期化処理を再度やり直せることだと思う。 初期化のタイミングで DB からのデータ取得を行なっているような場合だと初期値がどのようになるのかが DB に依存するが、ログアウト時に DB をクリアし、logoutProvider の値を変更すると DB の内容などは考慮する必要がなくなり都合が良い。

全体のフローの設計時の注意点としては、logoutProvider の値の変更前に DB やインメモリキャッシュをクリアしておくことだと思う。 各 provider の初期化処理で DB やメモリから値を取得している場合は、provider の再生成が走っても DB やインメモリキャッシュからデータを取得してしまい都合が悪い。

最後に

logout 時のローカルデータの処理は割とめんどくさいことが多い気がします。少しでも参考になれば幸いです。