Плохое состояние: поток уже прослушан с ошибкой

В моем приложении несколько потоков.

Это из примера приложения от appsflyer. Я использую его для глубинных ссылок на свое приложение.

https://pub.dev/packages/appsflyer_sdk

на первой странице у нас есть;

return Scaffold(
  appBar: AppBar(
    title: Column(
      children: <Widget>[
        Text('AppsFlyer SDK example app'),
        FutureBuilder<String>(
            future: _appsflyerSdk.getSDKVersion(),
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              return Text(snapshot.hasData ? snapshot.data : "");
            })
      ],
    ),
  ),
  body: FutureBuilder<dynamic>(
      future: _appsflyerSdk.initSdk(
          registerConversionDataCallback: true,
          registerOnAppOpenAttributionCallback: true),
      builder: (BuildContext context, AsyncSnapshot snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return Center(child: CircularProgressIndicator());
        } else {
          if (snapshot.hasData) {
            return HomeContainer(
              onData:
                  _appsflyerSdk.conversionDataStream?.asBroadcastStream(),
              onAttribution: _appsflyerSdk.appOpenAttributionStream
                  ?.asBroadcastStream(),
              trackEvent: logEvent,
            );
          } else {
            return Center(child: Text("Error initializing sdk"));
          }
        }
      }),
);

в HomeContainer

  Stream<Map> onData;
  Stream<Map> onAttribution;
  Future<bool> Function(String, Map) trackEvent;

  HomeContainer({this.onData, this.onAttribution, this.trackEvent});

внутренняя сборка;

Column(
            children: <Widget>[

              StreamBuilder<dynamic>(
              stream: widget.onData,
              builder:
                  (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
                return TextBorder(
                  controller: TextEditingController(
                      text: snapshot.hasData
                          ? Utils.formatJson(snapshot.data)
                          : "No conversion data"),
                  labelText: "Conversion Data:",
                );
              }),
              Padding(
                padding: EdgeInsets.only(top: 12.0),
              ),
              StreamBuilder<dynamic>(
              stream: widget.onAttribution,
              builder:
                  (BuildContext context, AsyncSnapshot<dynamic> snapshot) {
                return TextBorder(
                  controller: TextEditingController(
                      text: snapshot.hasData
                          ? _processData(snapshot.data)
                          : "No attribution data"),
                  labelText: "Attribution Data:",
                );
              }),
             
            ],
          ),

Что я сделал, так это поместил кнопку для перезагрузки экранов с помощью notifyListeners.

Когда я это сделаю, я получаю следующую ошибку:

Bad state: Stream has already been listened to.

Я предполагаю, что проблема может быть связана с тем, что эти потоки все еще открыты, когда я перезагружаю страницу.

Но я не знаю, как их закрыть.

Может ли кто-нибудь помочь в этом?


person Janaka    schedule 07.01.2021    source источник


Ответы (1)


StreamBuilder<dynamic>(
  stream: widget.onData?.asBroadcastStream(),

Вы вызываете asBroadcastStream() несколько раз (каждый раз, когда вызывается метод сборки) на widget.onData. Вы должны просто использовать:

StreamBuilder<dynamic>(
  stream: widget.onData,

И если widget.onData прослушивается где-то еще, убедитесь, что widget.onData сам является широковещательным потоком.

person spkersten    schedule 08.01.2021
comment
Спасибо за ваш ответ. Пробовал стрим: widget.onData, ошибка все еще есть. Есть ли еще что-нибудь, что я могу попробовать? - person Janaka; 08.01.2021
comment
Вторая часть ответа: убедитесь, что widget.onData сам является широковещательным потоком. Поэтому везде, где вы впервые получаете / создаете поток, используйте asBroadcastStream. - person spkersten; 08.01.2021
comment
Я не очень хорошо знаком с потоками. Я внес изменения в код, как вы предложили. Но я все еще получаю ту же ошибку. Актуальную версию кода я обновил в своем посте. Можете ли вы предложить решение? - person Janaka; 08.01.2021
comment
В методе построения FutureBuilder у вас есть два asBroadcastStream(). Методы build (er) можно вызывать несколько раз, поэтому вы не должны делать в них ничего, что должно происходить только один раз. Если вы удалите эти asBroadcastStream() вызовы, это может сработать (перестройка того же StreamBuilder с тем же потоком не заставит его снова его прослушивать, так что это нормально). - person spkersten; 08.01.2021
comment
Вторая вещь, которую вы делаете в методе build (er), который должен произойти только один раз, - это создание future (например, _appsflyerSdk.initSdk). Вам лучше делать эти вещи в месте, которое гарантирует, что они произойдут только один раз. Например, в методе main (если это инициализация некоторой глобальной сущности) или в initState StatefulWidget - person spkersten; 08.01.2021