Дважды вызвать Stream.stream.listen() с помощью StreamBuilder?

#flutter

#flutter

Вопрос:

Я использую StreamBuilder и добавляю StreamController.stream в него экземпляр.

 late StreamController c;
late Stream s;

initState() {
  c = StreamController();
  s = c.stream;
  super.initState();
}

Widget build(context) {
  return StreamBuilder(
    stream: s,
    builder: (context, snap) {
      return Container(
        child: TextButton(
          onPressed:() => setState(() {
            //calling setState will re-build StreamBuilder
          }),
        ),
      };
    }
  );
}
 

Поскольку StreamBuilder будет перестраиваться при каждом setState вызове, как мне StreamBuilder предотвратить попытку повторного прослушивания, Stream не превращая его в Broadcast поток (поскольку Stream s можно прослушать только один раз)?

Ответ №1:

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

Доказательства можно найти в реализации StreamBuilder и StreamBuilderBase в источнике Flutter. Действие выполняется только в том случае, если новый поток отличается от старого.

 @override
void didUpdateWidget(StreamBuilderBase<T, S> oldWidget) {
  super.didUpdateWidget(oldWidget);
  if (oldWidget.stream != widget.stream) {
    if (_subscription != null) {
      _unsubscribe();
      _summary = widget.afterDisconnected(_summary);
    }
    _subscribe();
  }
}
 

Комментарии:

1. Что делать, если StreamBuilder изменен? Например, если он был заменен другим виджетом в дереве, а затем StreamBuilder возвращается в ту же позицию?

2. @KernelJames Если это так, то StreamBuilder это не очень хороший вариант для того, что вы делаете. Вам нужно будет поддерживать подписку на поток в той точке дерева виджетов, где он не будет удален. Это может быть достигнуто путем удаления вашего StreamBuilder и прослушивания потока в initState виджета, который вы показываете в своем вопросе.