メインコンテンツに進む

StreamProvider

StreamProviderFutureProviderStream 版です。

一般的には次のような用途で使われます。

  • Firebase や WebSocket の監視するため。
  • 一定時間ごとに別のプロバイダを更新するため。

Stream 自体が値の更新を監視する性質を持つため、StreamProvider を使うことにあまり意義を見出せない方もいるかもしれません。 Flutter の StreamBuilder で十分ではないか、と。

しかし、StreamBuilder の代わりに StreamProvider を使うことで次の利点を得ることができます。

  • 他のプロバイダで ref.watch を通じてストリームを監視することができる。
  • AsyncValue により loading/error のステートを適切に処理することができる。
  • 通常のストリームとブロードキャスト(broadcast)ストリームを区別する必要がない。
  • ストリームから出力された直近の値をキャッシュしてくれる(途中で監視を開始しても最新の値を取得することができる)。
  • StreamProvider をオーバーライドすることでテスト時のストリームを簡単にモックすることができる。

使用例: ソケットを使ったライブチャット

StreamProviderは、ビデオストリーミングや天気予報のAPIなど非同期データのストリームを扱うときに使用されます。

final chatProvider = StreamProvider<List<String>>((ref) async* {
// Connect to an API using sockets, and decode the output
final socket = await Socket.connect('my-api', 4242);
ref.onDispose(socket.close);

var allMessages = const <String>[];
await for (final message in socket.map(utf8.decode)) {
// A new message has been received. Let's add it to the list of all messages.
allMessages = [...allMessages, message];
yield allMessages;
}
});

そして、UIはこのようにライブストリーミングチャットを監視することができます:

Widget build(BuildContext context, WidgetRef ref) {
final liveChats = ref.watch(chatProvider);

// Like FutureProvider, it is possible to handle loading/error states using AsyncValue.when
return switch (liveChats) {
// Display all the messages in a scrollable list view.
AsyncData(:final value) => ListView.builder(
// Show messages from bottom to top
reverse: true,
itemCount: value.length,
itemBuilder: (context, index) {
final message = value[index];
return Text(message);
},
),
AsyncError(:final error) => Text(error.toString()),
_ => const CircularProgressIndicator(),
};
}