Flutter のサーバー状態
サーバーデータに必要なのは、状態クラスをもう 1 つ増やすことではなく、キャッシュです。キャッシュは、すべての画面に同じコピーを渡します。読み込み中とエラーの状態を追跡し、古くなったデータを更新します。
Flutter アプリが表示するものの多くは、Todo のリスト、プロフィール、検索結果のページなど、サーバーから届きます。このデータは、アプリ自身が持つ状態とは違う振る舞いをします。
- アプリのものではありません。サーバー上で、アプリに知らせずに変わります。
- 共有されます。複数の画面が同じリストを表示し、その内容は一致している必要があります。
- 遅れて届くか、まったく届きません。読み取りのたびに、読み込み中の状態とエラーの状態があります。
- 古くなります。1 分前に取得したリストが、今は正しくないかもしれません。
選択中のタブなどのアプリの状態には、こうした問題はありません。
| アプリの状態 | サーバーデータ | |
|---|---|---|
| 変更する側 | アプリのコード | サーバー(いつでも) |
| 正しい値を持つ場所 | アプリ | どこか別の場所 |
| 届くタイミング | すぐ | 遅れて、または届かない |
| 古くなるか | いいえ | はい |
サーバーデータをアプリの状態と一緒に管理すると、キャッシュを自分で書くことになります。リポジトリ内のキャッシュ、画面ごとの読み込みフラグ、更新メソッド、書き込みのたびの無効化、2 つの画面が同時に要求したときのルールです。
キャッシュで得られるもの
Section titled “キャッシュで得られるもの”Fuery はサーバーデータをキーに紐づけて、1 つのキャッシュに保持します。
final todosQuery = Query( queryKey: ['todos'], queryFn: (_) => api.getTodos(),);この 1 つの定義から、次のものが得られます。
- キーごとに 1 つのコピー:
['todos']を使うすべての画面が、同じキャッシュエントリを読み取ります。 - 一度に 1 つのリクエスト:取得の実行中に要求した画面は、そのリクエストを共有します。
- 新鮮(fresh)から古い(stale)へ:データは
staleTimeの間だけ新鮮です(デフォルトはゼロなので、届いた時点で古くなります)。 - 古いデータは画面に残る:Fuery がバックグラウンドで再取得している間も、画面は古いデータを表示し続けます。
- 自動で再取得:画面が古いデータを使い始めたときと、アプリがフォアグラウンドに戻ったときに、Fuery は古いデータを再取得します。接続状態のソースを設定すると、ネットワークに再接続したときにも再取得します(ネットワークに再接続したとき)。
- 書き込みの後に再取得:ミューテーションの後で
['todos']を無効化すると、Fuery が画面上のリストを再取得します。 - 読み込み中とエラーの状態がデータと一緒に届く:結果には
status、error、isRefetchingなどのフラグが含まれます。そのため、画面は状態を自分で追跡せず、結果から読み取ります。 - 使われないデータはメモリから削除される:どの画面も使っていないデータを、ガベージコレクション時間の
gcTime(デフォルトは 5 分)が過ぎると、Fuery がメモリから削除します。永続化されたデータはデバイスに残ります。
キャッシュされたデータの各段階と、各段階が終わる条件は、クエリのライフサイクルにまとめています。
キャッシュが動く場所
Section titled “キャッシュが動く場所”キャッシュはウィジェットツリーの一部ではなく、普通の Dart オブジェクトです。同じクエリが次の 3 か所で動きます。
QueryBuilderが描画する- Cubit が
todosQuery.observe()のstreamをリッスンする - スクリプトが
client.query(todosQuery)を await する
Fuery は、すでに使っている状態管理を置き換えません。Cubit と Bloc の中でクエリを使う方法は、Bloc と Cubitで紹介しています。