StreamProvider
StreamProvider is similar to FutureProvider but for Streams instead of
Futures.
FutureProvider 与 Provider 类似,但用在 Stream 中而不是 Future。
StreamProvider 一般用于:
- 监听Firebase或web-sockets
- 每隔几秒重建另一个provider
由于 Stream 自然地公开了一种监听更新的方式,一些人可能认为使用 StreamProvider 没什么用。
特别是,你可能认为Flutter的 StreamBuilder  可以很好地用于监听流,但这是错误的。
在 StreamBuilder 上使用 StreamProvider 有很多好处:
- 它允许其他provider使用 ref.watch 监听流。
- 多亏了 AsyncValue ,它能确保加载和错误情况得到正确处理。
- 它消除了必须区分广播流和普通流的需要。
- 它缓存由流发出的最新值,确保如果在事件发出后添加监听器, 监听器仍然可以立即访问最新的事件。
- 它允许在测试期间通过覆盖 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(),
  };
}