颤动:状态不好:已经收听了Stream

问题描述 投票:19回答:4

    class MyPage extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return DefaultTabController(
          length: 2,
          child: new Scaffold(
            appBar: TabBar(
              tabs: [
                Tab(child: Text("MY INFORMATION",style: TextStyle(color: Colors.black54),)),
                Tab(child: Text("WEB CALENDER",style: TextStyle(color: Colors.black54),)),
              ],
            ),
            body:PersonalInformationBlocProvider(
              movieBloc: PersonalInformationBloc(),
              child: TabBarView(
                children: [
                  MyInformation(),
                  new SmallCalendarExample(),
                ],
              ),
            ),
          ),
        );
      }
    }

    class MyInformation extends StatelessWidget{
      // TODO: implement build
      var deviceSize;

      //Column1
      Widget profileColumn(PersonalInformation snapshot) => Container(
        height: deviceSize.height * 0.24,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceEvenly,
              children: <Widget>[
                Container(
                  decoration: BoxDecoration(
                    borderRadius:
                    new BorderRadius.all(new Radius.circular(50.0)),
                    border: new Border.all(
                      color: Colors.black,
                      width: 4.0,
                    ),
                  ),
                  child: CircleAvatar(
                    backgroundImage: NetworkImage(
                        "http://www.binaythapa.com.np/img/me.jpg"),
                    foregroundColor: Colors.white,
                    backgroundColor: Colors.white,
                    radius: 40.0,
                  ),
                ),
                ProfileTile(
                  title: snapshot.firstName,
                  subtitle: "Developer",
                ),
                SizedBox(
                  height: 10.0,
                ),
              ],
            )
          ],
        ),
      );
      Widget bodyData(PersonalInformation snapshot) {
        return SingleChildScrollView(
            child: Column(
              children: <Widget>[
                profileColumn(snapshot)
              ],
            ),
        );
      }


      @override
      Widget build(BuildContext context) {
        final personalInformationBloc = PersonalInformationBlocProvider.of(context);

        deviceSize = MediaQuery.of(context).size;
        return StreamBuilder(
            stream: personalInformationBloc.results,
            builder: (context,snapshot){
              if (!snapshot.hasData)
                return Center(
                  child: CircularProgressIndicator(),
                );
              return bodyData(snapshot.data);
            }
        );
      }
    }


我正在使用Bloc Pattern从Rest API中检索数据(仅从json调用整个对象并仅解析用户名)。该页面包含两个选项卡MyIformation和SmallCalendar。当应用程序运行时,数据被正确获取并且一切都很好。当我转到选项卡二并返回选项卡一时,选项卡一中的整个屏幕变为红色显示错误:Bad state: Stream has already been listened to.

dart flutter
4个回答
23
投票

您应该使用以下内容。

StreamController<...> _controller = StreamController<...>.broadcast();

10
投票

最常见的Stream形式一次只能听一次。如果您尝试添加多个侦听器,它将抛出

状态不好:已经收听了Stream

要防止此错误,请公开广播Stream。您可以使用myStream.asBroadcastStream将流转换为广播

这需要在暴露Stream的类中完成。不作为StreamBuilder的参数。由于asBroadcastStream在内部侦听原始流以生成广播流,因此这意味着您无法在同一个流上调用此方法两次。


4
投票

问题是由于没有将控制器部署在集团中。

  void dispose() {
    monthChangedController.close();
    dayPressedController.close();
    resultController.close();
  }

2
投票

在我的情况下,我收到此错误,因为相同的代码行myStream.listen()在同一个流中的同一个小部件中被调用了两次。显然这是不允许的!

为我修复的是将我的流控制器创建为广播流控制器:

var myStreamController = StreamController<bool>.broadcast();

使用流作为广播流:

myStreamController.stream.asBroadcastStream().listen(onData);

0
投票

当我将StreamBuilder的Observable.combineLatest2的结果用于Drawer时,我遇到了同样的问题:

扑腾:糟糕的状态:已经听过Stream了。

至于我,最好的解决方案是将这个组合的结果添加到新的BehaviorSubject并听取新的。

别忘了听老人!!!

class VisitsBlocc extends Object {
    Map<Visit, Location> visitAndLocation;

    VisitsBloc() {
        visitAndLocations.listen((data) {
            visitAndLocation = data;
        });
    }

    final _newOne = new BehaviorSubject<Map<Visit, Location>>();

    Stream<Map<Visit, Location>> get visitAndLocations => Observable.combineLatest2(_visits.stream, _locations.stream, (List<vis.Visit> visits, Map<int, Location> locations) {
        Map<vis.Visit, Location> result = {};

        visits.forEach((visit) {
            if (locations.containsKey(visit.skuLocationId)) {
                result[visit] = locations[visit.skuLocationId];
            }
        });

        if (result.isNotEmpty) {
            _newOne.add(result);
        }
    });
}

我没有使用.broadcast,因为它减慢了我的UI。

© www.soinside.com 2019 - 2024. All rights reserved.