我正在尝试使用bloc模式来管理来自API的数据,并将其显示在我的小部件中。我能够从API提取数据并对其进行处理并显示,但是我使用的是底部导航栏,当我更改选项卡并转到上一个选项卡时,它将返回此错误:
未处理的异常:错误状态:调用close后无法添加新事件。
我知道这是因为我正在关闭流,然后尝试对其进行添加,但是我不知道如何解决它,因为不处理publishsubject将导致memory leak。这是我的UI代码:
publishsubject
memory leak
class CategoryPage extends StatefulWidget { @override _CategoryPageState createState() => _CategoryPageState(); } class _CategoryPageState extends State<CategoryPage> { @override void initState() { serviceBloc.getAllServices(); super.initState(); } @override void dispose() { serviceBloc.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return StreamBuilder( stream: serviceBloc.allServices, builder: (context, AsyncSnapshot<ServiceModel> snapshot) { if (snapshot.hasData) { return _homeBody(context, snapshot); } if (snapshot.hasError) { return Center( child: Text('Failed to load data'), ); } return CircularProgressIndicator(); }, ); } } _homeBody(BuildContext context, AsyncSnapshot<ServiceModel> snapshot) { return Stack( Padding( padding: EdgeInsets.only(top: screenAwareSize(400, context)), child: _buildCategories(context, snapshot)) ], ); } _buildCategories(BuildContext context, AsyncSnapshot<ServiceModel> snapshot) { return Padding( padding: EdgeInsets.symmetric(vertical: 20), child: GridView.builder( gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, crossAxisSpacing: 3.0), itemCount: snapshot.data.result.length, itemBuilder: (BuildContext context, int index) { return InkWell( child: CategoryWidget( title: snapshot.data.result[index].name, icon: Icons.phone_iphone, ), onTap: () {}, ); }, ), ); }
这是我的集团代码:
class ServiceBloc extends MainBloc { final _repo = new Repo(); final PublishSubject<ServiceModel> _serviceController = new PublishSubject<ServiceModel>(); Observable<ServiceModel> get allServices => _serviceController.stream; getAllServices() async { appIsLoading(); ServiceModel movieItem = await _repo.getAllServices(); _serviceController.sink.add(movieItem); appIsNotLoading(); } void dispose() { _serviceController.close(); } } ServiceBloc serviceBloc = new ServiceBloc();
我没有包含回购和API代码,因为它不在此错误的主题之内。
如果错误实际上是由您发布的代码引起的,那么我将添加一个检查以确保在dispose()调用之后不添加任何新事件。
dispose()
class ServiceBloc extends MainBloc { final _repo = new Repo(); final PublishSubject<ServiceModel> _serviceController = new PublishSubject<ServiceModel>(); Observable<ServiceModel> get allServices => _serviceController.stream; getAllServices() async { // do nothing if already disposed if(_isDisposed) { return; } appIsLoading(); ServiceModel movieItem = await _repo.getAllServices(); _serviceController.sink.add(movieItem); appIsNotLoading(); } bool _isDisposed = false; void dispose() { _serviceController.close(); _isDisposed = true; } } ServiceBloc serviceBloc = new ServiceBloc();