コンテンツにスキップ

ストリーミングクエリ

streamedQuery は Stream をクエリ関数に変えます。チャンクが届いている間、画面はデータを表示します。ストリームが終わると、キャッシュが結果を保持します。

ストリーミングで返る回答、進捗ログ、処理中のファイルなど、チャンクで届いて最後に終わるレスポンスに使ってください。ライブフィードのように開いたままの接続は取得ではないので、クエリには向きません。その場合は、キャッシュを読み書きするのように、各メッセージを setQueryData でキャッシュに書き込んでください。

final answer = Query(
queryKey: ['answer', question],
queryFn: streamedQuery(
stream: (context) => api.ask(question),
initialValue: '',
combine: (text, token) => text + token,
),
);
  • 最初のチャンクでクエリが成功します。データが増えるにつれて、ウィジェットがそのデータを表示します。
  • ストリームが終わるまで isFetching は true のままです。
  • combine は Stream.fold と同じように動きます。initialValue から始めて、それまでの値にチャンクを 1 つずつ加えます。
  • initialValue がデータ型を決めるので、呼び出しに型引数は不要です。
  • 空のストリームは initialValue で成功します。
  • ストリームや combine でエラーが起きると、クエリは失敗します。data には、それまでに受け取ったチャンクが残ります。
  • 再試行のたびに新しいストリームを開始し、refetchMode に従います。デフォルトのモードでは、最初にデータを消去します。

Query は、staleTime などのほかのクエリのオプションも通常どおり受け取ります。

空のリストから始めて、各チャンクを追加してください。

final log = Query(
queryKey: ['jobs', id, 'log'],
queryFn: streamedQuery(
stream: (context) => api.jobLog(id),
initialValue: const <LogLine>[],
combine: (lines, line) => [...lines, line],
),
);

ストリーミングクエリを再取得する

Section titled “ストリーミングクエリを再取得する”

refetchMode は、invalidateQueries の後などにクエリがもう一度取得するとき、キャッシュされたデータをどう扱うかを決めます。

モード 新しいストリームの実行中 完了時
StreamRefetchMode.reset(デフォルト) Fuery がデータを消去し、最初のチャンクが届くまでクエリは pending になります。 新しいデータ
StreamRefetchMode.append Fuery が新しいチャンクを既存のデータに畳み込みます。 結合されたデータ
StreamRefetchMode.replace 古いデータが画面に残ります。 新しいデータ(一度にまとめて)
queryFn: streamedQuery(
stream: (context) => api.ask(question),
initialValue: '',
combine: (text, token) => text + token,
refetchMode: StreamRefetchMode.replace,
),

Fuery は、取得をキャンセルするときにストリームもキャンセルします。cancelQueries のときと、再取得が実行中の取得を置き換えるときです。

デフォルトでは、どのウィジェットもクエリを使っていなくてもストリームは動き続け、Fuery が結果をキャッシュします。そのため、ユーザーが戻ってきたときには、ストリーミングの回答は完成しています。代わりにストリームを止めるには、stream の中で context.signal を読んでください。すると、取得がキャンセル可能になります。

stream: (context) {
final request = api.startAnswer(question); // a request you can cancel
context.signal.onAbort(request.cancel);
return request.tokens;
},

サンプルアプリは、投稿画面でスレッドの要約をストリーミングしています。README では、各画面とその画面で示している機能を対応づけています。