Stream builder delay issue in flutter

Issue

I have a stream builder, but it shows a different stream Query depends on user selection.

There is a problem when using changes the selection, that there is a small delay between getting the stream Query of the selection, so very briefly, the previous query shows up and changes to the selected query right away. I am wondering is there any way that I can prevent showing the query during that delay time.

  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(),

Solution

Refer to official documentation of StreamBuilder: https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html#widgets.StreamBuilder.1

Inside of StreamBuilder builder method there is a AsyncSnapshot value, which has not only the data of the Stream, but also the state and errors. Inside of your builder method, check for snapshot.hasError, and snapshot.state. There are 4 states of the connection:

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,
}

Your "delay" is caused due to switches between these states, so ideally you need to specify the return for every state. Refer to full example, taken from documentation:

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,
          );
        },
      ),
    ],
  ),
);

Answered By – Maksim Nikolaev

Answer Checked By – Willingham (FlutterFixes Volunteer)

Leave a Reply

Your email address will not be published. Required fields are marked *