Flutter の流儀で設計
クエリを表示する画面は StatelessWidget のままです。クエリは build の外で定義します。ウィジェットは、StreamBuilder がストリームを描画するのと同じようにクエリを描画します。UI はビルダーが、副作用はリスナーが受け持ちます。何も置き換えずに、1 画面ずつ Fuery を導入できます。フックを使う場合は、独立したパッケージの fuery_hooks が useQuery で同じクエリを描画します。
// A Query<List<Todo>>, with no type arguments.final todos = Query( queryKey: ['todos'], queryFn: (_) => api.getTodos(),);
QueryBuilder( query: todos, builder: (context, state) => switch (state.data) { final data? => TodoList(data), // a List<Todo> null => const CircularProgressIndicator(), },)サーバーデータにキャッシュが必要な理由は、Flutter のサーバー状態で説明しています。ミューテーションはサーバーデータを作成、更新、削除します。楽観的更新も使えます。
Flutter の流儀で設計
クエリを表示する画面は StatelessWidget のままです。クエリは build の外で定義します。ウィジェットは、StreamBuilder がストリームを描画するのと同じようにクエリを描画します。UI はビルダーが、副作用はリスナーが受け持ちます。何も置き換えずに、1 画面ずつ Fuery を導入できます。フックを使う場合は、独立したパッケージの fuery_hooks が useQuery で同じクエリを描画します。
Dart と Flutter 以外に依存しない
コード生成も、ネイティブコードも、プラットフォームごとの設定も不要です。コアは純粋な Dart で、依存するのは Dart チームの clock、collection、meta だけです。ウィジェット、Cubit、Bloc、サービス、CLI、サーバーが同じクエリオブジェクトを使います。
キャッシュされ、新鮮に保たれる
キーが同じウィジェットはすべて、同じキャッシュエントリとリクエストを共有します。Fuery がバックグラウンドで再取得している間も、古いデータは画面に表示されたままです。再取得で返った項目が == で等しい場合、Fuery は以前のオブジェクトを保持します。そのため、その項目を表示するリストの行はリビルドされません。
関数から決まる型
クエリ、ミューテーション、無限クエリは、それぞれの関数から型を受け取ります。ウィジェット、結果、コールバックは、型引数なしでその型を引き継ぎます。型を明示するのは 2 つの場合です。getQueryData<List<Todo>>(['todos']) のようにキーだけで読み書きする場合と、最初のページパラメーターが null の無限クエリです。
現実のネットワークに対応
画面に表示中のクエリは、失敗した取得をバックオフ付きで 3 回再試行します。アプリが再開すると再取得もします。接続状態のソースを設定すると、デバイスがオフラインの間は一時停止し、再接続すると再取得します。クエリを使うものがなくなると、Fuery は context.signal を読むクエリ関数をキャンセルします。このキャンセルはエラーとして報告しません。クエリは、条件が満たされるまでポーリングすることも、ストリームを畳み込んでキャッシュに入れることもできます。
永続化と中身の確認
テスト済み:すべてのパッケージが行カバレッジ 100% で、カバーされない行が出ると CI が失敗します。テストは、サポートする最も古い Flutter(3.27)と最新版で実行します。コアのテストはフェイクの時間で実行します。回帰テストスイートが、修正済みのエッジケースが再発しないようにしています。Fuery は破棄の過程ですべてのタイマーをキャンセルし、時刻を package:clock から読み取ります。そのため、独自の fake_async テストやウィジェットテストでも、タイマーがリークしません。テストを参照してください。
Fuery のキャッシュと再取得のモデルは、TanStack Query から着想を得ています。TanStack Query の各概念に対応する Fuery の名前は、TanStack Query を使ってきた方へで紹介しています。