我试图使用bloc模式来管理API中的数据,并在我的小部件中显示它们.我可以从API中获取数据并进行处理和显示,但我使用的是底部导航栏,当我更改选项卡并转到上一个选项卡时,它会返回以下错误:

未处理的异常:状态错误:调用后无法添加新事件 关.

我知道这是因为我正在关闭流,然后try 添加它,但我不知道如何修复它,因为不处理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();

我没有包括repo和API代码,因为它不在此错误的主题中.

推荐答案

如果错误实际上是由您发布的代码引起的,我只需要添加一个判断,以确保在调用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();

Flutter相关问答推荐

为什么小部件会在其父文件中重建,但放在单独文件中时却不会重建?

如何更新文本字段的基础上的选定下拉菜单?

使用自定义控制器将项插入到ListView中时行为不正确

如果文档确实存在,则FiRestore将";False";返回到";if-Document-Existes";...还是我说错了?

如何处理Flutter Riverpod异步通知器中的状态和数据库

我不能在Fighting中裁剪图片输入错误,否则应用程序会崩溃

如何实现Flutter 梳理机图像的小量移动

在Flutter 中每次点击按钮时都很难调用自定义函数

如何使文本表格域在抖动中变圆?

Flutter如何将2个以上的值传递到ListView上的另一个屏幕?

#Flutter/Riverpod - 使用 AsyncNotifier 时是否可以仅调用错误?

Flutter - 根据从第一个 DropdownButtonForm 中 Select 的内容在第二个 DropdownButton 上显示选项

如何修复 ICU Lexing 错误:Flutter 中的意外字符

将 String 与 List 元素进行比较时出现问题

Flutter sliver 持久化

有没有办法为文本中的下划线创建自定义样式?

Flutter中如何连续获取TextField的文本是否为空?

Flutter Web App 未启动:脚本的 MIME 类型不受支持

使用 Firebase/Flutter 进行应用判断 - 100% 无效请求

Flutter:整个判断整个应用生命周期的通用类