StreamBuilder
和FutureBuilder
之间的主要区别是什么?
使用什么以及何时使用?
他们打算执行哪些任务?
他们每个人如何收听动态列表中的更改?
答案 0 :(得分:28)
StreamBuilder
和FutureBuilder
都有相同的行为:它们会侦听各自对象的更改。并在收到通知时触发新构建
一个新的价值。
所以最后,他们的不同之处在于他们听的对象是如何运作的。
Future
与JS中的Promise
或c#中的Task
类似。它们是异步请求的表示。 Futures
只有一个回复。 Future
的常见用法是处理http调用。您可以在Future
上听到的是它的状态。无论是完成,成功完成还是出错。但就是这样。
Stream
就像JS中的异步Iterator
。这可以被同化为可以随时间变化的值。它通常是Web套接字或事件(例如单击)的表示。通过收听Stream
,您将获得每个新值,以及Stream
是否有错误或已完成。
他们每个人如何收听动态列表中的更改?
Future
无法收听变量。这是一次性的回应。相反,您需要使用Stream
。
答案 1 :(得分:5)
我发现有时真实世界的类比可以很好地解释/记住概念。这是一个-并不完美,但对我有帮助。
以为您在那些现代寿司餐厅之一,那里的皮带环绕着整个房间,上面挂着寿司船。您只需坐下,等到路过时,抓住它并吃东西。但是它们还允许您订购执行。
未来就像带有令牌的令牌,在您订购外卖时会给您;您提出了请求,但结果尚未准备好,但您有一个占位符。结果准备好后,您会得到一个回叫(外卖柜台上方的数字标牌显示您的电话号码,或者他们大声喊叫)-现在您可以进去拿食物(结果)取出。
溪流就像一条带小寿司碗的皮带。通过坐在那张桌子,您已经“订阅”了信息流。您不知道下一艘寿司船何时到达-但当厨师(消息源)将其放入溪流(皮带)中时,订户将收到它。需要注意的重要一点是,它们是异步到达的(您不知道什么时候下一条船/消息会到达),但是它们会依次到达(即,如果厨师将三种类型的寿司按一定顺序放在皮带上,您将看到它们以相同的顺序从您身边走来
从编码的角度来看-期货和流技术都可以帮助您处理异步问题(事情不会立即发生,并且您不知道何时)请求)。
区别在于,Future只是一次请求/响应(我问,有一个延迟,我收到一条通知,告知我Future已准备好收集,我已经完成!),而Streams是连续的序列单个请求的响应数(我问,有一个延迟,然后我会不断获取响应,直到流耗尽或决定关闭它然后走开)。
希望有帮助。
答案 2 :(得分:1)
FutureBuilder
用于一次响应,例如从相机拍摄图像,从本机平台获取一次数据(例如获取设备电池),获取文件引用,发出http请求等。
另一方面,StreamBuilder
用于多次获取某些数据,例如听位置更新,播放音乐,秒表等。
以下是完整的示例,其中提到了两种情况。
FutureBuilder
求解一个平方值,并在5秒钟后返回结果,直到我们向用户显示进度指示器。
StreamBuilder
显示秒表,每秒将_count
的值增加1。
void main() => runApp(MaterialApp(home: HomePage()));
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _count = 0; // used by StreamBuilder
@override
Widget build(BuildContext context) {
return Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
_buildFutureBuilder(),
SizedBox(height: 24),
_buildStreamBuilder(),
],
),
);
}
// constructing FutureBuilder
Widget _buildFutureBuilder() {
return Center(
child: FutureBuilder<int>(
future: _calculateSquare(10),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done)
return Text("Square = ${snapshot.data}");
return CircularProgressIndicator();
},
),
);
}
// used by FutureBuilder
Future<int> _calculateSquare(int num) async {
await Future.delayed(Duration(seconds: 5));
return num * num;
}
// constructing StreamBuilder
Widget _buildStreamBuilder() {
return Center(
child: StreamBuilder<int>(
stream: _stopwatch(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active)
return Text("Stopwatch = ${snapshot.data}");
return CircularProgressIndicator();
},
),
);
}
// used by StreamBuilder
Stream<int> _stopwatch() async* {
while (true) {
await Future.delayed(Duration(seconds: 1));
yield _count++;
}
}
}
答案 3 :(得分:0)
FutureBuilder
它只有一个响应。 flutter Future 的一个非常常见的用法是在 http 调用期间。你可以用 Future 做的是监听它的状态,也就是说,当它完成或在通过 Future 获取数据完成后发生错误时
对于 FutureBuilder,我们在 Flutter 文档中阅读了此警告:
未来一定是更早得到的,...... 如果未来与 FutureBuilder 同时创建, 那么每次FutureBuilder的父级重建时,异步任务都会重新启动。
在许多教程中,我看到这样的内容:
FutureBuilder(
future : foo.asyncMethod();
builder : (context, snapshot){
}
)
这不好,因为每次调用构建过程都会调用异步方法并调用 FutureBuilder 的构建器。
如果您的用例只是获取数据并显示它,例如来自 API 的类中的课程总数。然后您可以使用 FutureBuilder
。
StreamBuilder
另一方面,Stream 是迭代器,它可以吸收不同的值,这些值会随着时间而改变。通过使用 Stream,您将获得每个新值以及是否有错误或成功消息
如果在您使用应用时数据每秒或每分钟更新一次,例如博客中即将发布的帖子或增加对博客的评论或增加对博客的喜欢,该怎么办?它以特定间隔异步更新,在这种情况下,StreamBuilder
是最佳选择。