Iganinのブログ

日頃の開発で学んだ知見を中心に記事を書いています。

【Flutter】RiverpodのProviderのキャッシュをLogout時に効率的に削除する

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