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.
您应该使用以下内容。
StreamController<...> _controller = StreamController<...>.broadcast();
最常见的Stream
形式一次只能听一次。如果您尝试添加多个侦听器,它将抛出
状态不好:已经收听了Stream
要防止此错误,请公开广播Stream
。您可以使用myStream.asBroadcastStream
将流转换为广播
这需要在暴露Stream
的类中完成。不作为StreamBuilder
的参数。由于asBroadcastStream
在内部侦听原始流以生成广播流,因此这意味着您无法在同一个流上调用此方法两次。
问题是由于没有将控制器部署在集团中。
void dispose() {
monthChangedController.close();
dayPressedController.close();
resultController.close();
}
在我的情况下,我收到此错误,因为相同的代码行myStream.listen()
在同一个流中的同一个小部件中被调用了两次。显然这是不允许的!
为我修复的是将我的流控制器创建为广播流控制器:
var myStreamController = StreamController<bool>.broadcast();
和
使用流作为广播流:
myStreamController.stream.asBroadcastStream().listen(onData);
当我将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。