【问题标题】:Stream builder delay issue in flutter颤动中的流构建器延迟问题
【发布时间】:2021-09-25 09:18:02
【问题描述】:

我有一个流生成器,但它显示不同的流查询取决于用户选择。

使用更改选择时存在一个问题,即在获取选择的流查询之间有一个小的延迟,因此非常简单,之前的查询显示并立即更改为选定的查询。我想知道有什么方法可以阻止在延迟时间内显示查询。

  body: ListView(
    children: <Widget>[
  select(),// decide buyOrSell
  StreamBuilder(
      stream: buyOrSell == "buy"
          ? FirebaseFirestore.instance
              .collection("buy")
              .doc(widget.profileId)
              .collection("barter")
              .orderBy('timestamp', descending: true)
              .snapshots()
          : FirebaseFirestore.instance
              .collection("sell")
              .doc(widget.profileId)
              .collection("barter")
              .orderBy('timestamp', descending: true)
              .snapshots(),

【问题讨论】:

    标签: flutter dart flutter-test


    【解决方案1】:

    参考StreamBuilder官方文档:https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html#widgets.StreamBuilder.1

    StreamBuilder builder方法里面有一个AsyncSnapshot值,里面不仅有Stream的数据,还有状态和错误。在您的 builder 方法中,检查 snapshot.hasError 和 snapshot.state。连接有4种状态:

    enum ConnectionState {
      /// Not currently connected to any asynchronous computation.
      ///
      /// For example, a [FutureBuilder] whose [FutureBuilder.future] is null.
      none,
    
      /// Connected to an asynchronous computation and awaiting interaction.
      waiting,
    
      /// Connected to an active asynchronous computation.
      ///
      /// For example, a [Stream] that has returned at least one value, but is not
      /// yet done.
      active,
    
      /// Connected to a terminated asynchronous computation.
      done,
    }
    

    您的“延迟”是由于这些状态之间的切换造成的,因此理想情况下,您需要为每个状态指定返回。请参阅完整示例,取自文档:

    return Scaffold(
      body: ListView(
        children: <Widget>[
          select(), // decide buyOrSell
          StreamBuilder(
            stream: buyOrSell == "buy"
                ? FirebaseFirestore.instance
                    .collection("buy")
                    .doc(widget.profileId)
                    .collection("barter")
                    .orderBy('timestamp', descending: true)
                    .snapshots()
                : FirebaseFirestore.instance
                    .collection("sell")
                    .doc(widget.profileId)
                    .collection("barter")
                    .orderBy('timestamp', descending: true)
                    .snapshots(),
            builder: (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
              List<Widget> children;
              if (snapshot.hasError) {
                children = <Widget>[
                  const Icon(
                    Icons.error_outline,
                    color: Colors.red,
                    size: 60,
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 16),
                    child: Text('Error: ${snapshot.error}'),
                  ),
                  Padding(
                    padding: const EdgeInsets.only(top: 8),
                    child: Text('Stack trace: ${snapshot.stackTrace}'),
                  ),
                ];
              } else {
                switch (snapshot.connectionState) {
                  case ConnectionState.none:
                    children = const <Widget>[
                      Icon(
                        Icons.info,
                        color: Colors.blue,
                        size: 60,
                      ),
                      Padding(
                        padding: EdgeInsets.only(top: 16),
                        child: Text('Select a lot'),
                      )
                    ];
                    break;
                  case ConnectionState.waiting:
                    children = const <Widget>[
                      SizedBox(
                        child: CircularProgressIndicator(),
                        width: 60,
                        height: 60,
                      ),
                      Padding(
                        padding: EdgeInsets.only(top: 16),
                        child: Text('Awaiting bids...'),
                      )
                    ];
                    break;
                  case ConnectionState.active:
                    children = <Widget>[
                      const Icon(
                        Icons.check_circle_outline,
                        color: Colors.green,
                        size: 60,
                      ),
                      Padding(
                        padding: const EdgeInsets.only(top: 16),
                        child: Text('\$${snapshot.data}'),
                      )
                    ];
                    break;
                  case ConnectionState.done:
                    children = <Widget>[
                      const Icon(
                        Icons.info,
                        color: Colors.blue,
                        size: 60,
                      ),
                      Padding(
                        padding: const EdgeInsets.only(top: 16),
                        child: Text('\$${snapshot.data} (closed)'),
                      )
                    ];
                    break;
                }
              }
    
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.center,
                children: children,
              );
            },
          ),
        ],
      ),
    );
    

    【讨论】: