跳到主要内容

StreamProvider

StreamProvider is similar to FutureProvider but for Streams instead of Futures. FutureProviderProvider 类似,但用在 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(),
};
}