目的
Riverpodが提供するProviderは、値をキャッシュしてbuildのたびに処理が動かないようにしてくれている。 FutureProviderでWebAPIをコールする処理がbuildの度に実行されないのは便利だ。
しかし、キャッシュを使いたくないと思っていたのに使われていたということも起こりがちなので、どういう場合にキャッシュが使われるのかを把握しておくことは重要だ。
今回は、下記のパターンでキャッシュが使われるかどうかを確認した。
Providerのパターン
- 基本のProvider
- 内部にref.watch(値が変化する)を持つProvider
- 引数ありで引数が毎回変化する (Provider.family)
- 引数ありで引数は常に一定の値 (Provider.family)
- 自動破棄 (Provider.autoDispose)
状況のパターン
WidgetにてそれぞれのProviderをref.watchして、下記の状況でキャッシュが返却されるかどうかを確認する。
- buildする
- build後、再度buildする(リビルド)
- build後、画面をdisposeして再度build
結果
パターンbで結果が分かれる理由
Riverpodの仕様で、下記の場合は再計算を行うから。
- 内部のref.watchの値が変化した場合
- 引数の値が変化した場合
パターンcで結果で分かれる理由
autoDisposeを指定している場合、画面がdisposeされProviderをwatchするWidgetがなくなると、Providerは破棄される。 その後、画面を再度生成すると、パターンaと同様の状況になり値が新規に計算される。
一方、1~4のProvoderは画面の破棄だけでは影響をうけないので、更新や破棄などが発生せずキャッシュが返却される。(画面の破棄によって影響を受けるように作れば当然再計算されます。)
実装で気を付けること
画面と同じ寿命を持つProvoderにはautoDisposeをつける
例えば、ポップアップ画面を表示する際に最新のデータをProviderで取得して表示する。という機能があるとする。
この場合、一度画面を閉じて再度開いた時には最新の値が表示されることが期待される(キャッシュをだしてほしくない)ので、autoDisposeを指定しておくことが望ましい。
そすれば、画面が破棄されるのと同時にProviderは破棄され、再度画面を開いた際にProviderが再び値を再計算してくれる。
FutureProviderでWebAPIをたたく場合
現在時刻を返却する、引数のないWebAPIがあるとする。このAPIにFutureProviderでアクセスして値を取得し、画面表示する機能を考える。
今回の結果から言うと、このFutureProviderはリビルドを行っても毎回キャッシュを返却してしまう。
ビルドのたびに常に最新の値を取得したいというニーズがある場合は、FutureProviderの内部にref.watchを配置するなどの工夫を行う必要がある。