StreamProvider
StreamProvider
は FutureProvider の Stream 版です。
一般的には次のような用途で使われます。
- 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(),
};
}