Проблема задержки построителя потоков в flutter

#flutter #dart #flutter-test

Вопрос:

У меня есть конструктор потоков, но он показывает другой запрос потока, который зависит от выбора пользователя.

При использовании изменений выбора возникает проблема, связанная с небольшой задержкой между получением потокового запроса выбора, поэтому очень кратко отображается предыдущий запрос и сразу же изменяется выбранный запрос. Мне интересно, есть ли какой-либо способ предотвратить отображение запроса в течение этого времени задержки.

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

Ответ №1:

Обратитесь к официальной документации StreamBuilder: https://api.flutter.dev/flutter/widgets/StreamBuilder-class.html#widgets.Потокостроитель.1

Внутри метода StreamBuilder builder есть значение AsyncSnapshot, которое содержит не только данные потока, но также состояние и ошибки. Внутри вашего метода построения проверьте наличие 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,
          );
        },
      ),
    ],
  ),
);