114

StreamBuilder和之间的主要区别是什么FutureBuilder

  • 使用什么以及何时使用?

  • 他们打算执行什么任务?

  • 他们每个人如何监听动态列表中的变化?

4

4 回答 4

180

两者都StreamBuilder具有FutureBuilder相同的行为:它们监听各自对象的变化。并在收到新值通知时触发新构建。

所以最后,他们的不同之处在于他们所听的对象是如何工作的。

Future就像Promise在 JS 或Taskc# 中一样。它们是异步请求的表示。Futures有一个且只有一个响应。的一个常见用法Future是处理 HTTP 调用。您可以在 a 上听到的Future是它的状态。无论是完成、成功完成还是出现错误。但就是这样。

Stream另一方面就像IteratorJS 中的异步。这可以被同化为一个可以随时间变化的值。它通常是网络套接字或事件(如点击)的表示。通过收听,Stream您将获得每个新值,以及是否Stream有错误或已完成。

他们每个人如何监听动态列表中的变化?

AFuture听不到变量的变化。这是一次性响应。相反,您需要使用Stream.

于 2018-06-13T19:31:47.397 回答
56

FutureBuilder用于一次性响应,例如从 Camera 获取图像、从原生平台获取一次数据(例如获取设备电池)、获取文件引用、发出 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++;
    }
  }
}
于 2019-05-30T12:50:17.830 回答
36

我发现有时现实世界的类比可以很好地解释/记住概念。这是一个 - 它并不完美,但它对我有帮助。

想想你在那些现代寿司餐厅之一,你有一条腰带绕着房间走,上面有寿司船。你只是坐下来等一个人经过,抓住它吃。但它们也允许您订购执行。

未来就像你点外卖时给你的带有数字的代币;您提出了请求,但结果尚未准备好,但您有一个占位符。当结果准备好时,您会收到回电(外卖柜台上方的数字板显示您的号码或他们喊出来)-您现在可以进去拿食物(结果)取出。

一条溪流就像那条带着小寿司碗的腰带。通过坐在那张桌子旁,您已经“订阅”了流。您不知道下一艘寿司船什么时候到达 - 但是当厨师(消息源)将其放入流(传送带)时,订阅者就会收到它。需要注意的重要一点是它们是异步到达的(您不知道下一条船/消息何时到达)但它们会按顺序到达(即,如果厨师按顺序将三种寿司放在腰带上——您会看到它们以相同的顺序从您身边而来)

从编码的角度来看——Futures 和 Streams 都可以帮助您处理异步(事情不会立即发生,并且您不知道在发出请求后何时会得到结果)。

不同之处在于,Futures 是关于一次性请求/响应(我问,有延迟,我收到通知说我的 Future 已准备好收集,我已经完成了!)而 Streams 是对一个请求(我问,有一个延迟,然后我不断收到响应,直到流干涸或我决定关闭它并走开)。

希望有帮助。

于 2020-01-06T10:55:04.710 回答
2

未来建造者

它只有一个响应。Flutter Future 的一个非常常见的用法是在 http 调用期间。你可以用 Future 做的是监听它的状态,即当它完成或者通过 Future 完成获取数据后发生错误时

对于 FutureBuilder,我们在 Flutter 文档中阅读了这个警告:

未来肯定是更早获得的,......

在许多教程中,我看到类似这样的内容:

FutureBuilder(
    future : foo.asyncMethod();
    builder : (context, snapshot){

    }
)

这不好,因为每次调用构建过程都会调用异步方法并调用 FutureBuilder 的构建器。

如果您的用例只是获取数据并显示它,例如来自 API 的类的课程总数。然后你可以使用FutureBuilder.

流生成器

另一方面,流是迭代器,它可以吸收不同的值,这些值会随着时间而变化。通过使用 Stream,您将获得每个新值,并且如果它有一些错误或者它完成了成功消息

如果,当您使用该应用程序时,数据每秒或每分钟更新一次,例如博客中即将发布的帖子或增加对博客的评论或增加对博客的喜欢。它以一定的间隔异步更新,在这种情况下StreamBuilder是最好的选择。

于 2021-04-16T03:20:48.050 回答