坏状态: Flutter Modular 在调用close之后无法添加新事件

5
我在返回首页并第二次访问产品页面时,遇到了以下错误"Bad State: Cannot add new events after calling close"。 第一次加载产品时没有问题,但再次加载产品页面时会抛出此错误。
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_modular/flutter_modular.dart';

import '../../widgets/product_display.dart';
import '../../widgets/title_section.dart';
import '../home_page/components/button_menu.dart';
import 'bloc/products_bloc.dart';
import 'bloc/products_event.dart';
import 'bloc/products_state.dart';

class ProductsPage extends StatefulWidget {
  const ProductsPage({Key? key}) : super(key: key);

  @override
  State<ProductsPage> createState() => _ProductsPageState();
}

class _ProductsPageState extends State<ProductsPage> {
  final bloc = Modular.get<ProductsBloc>();

  @override
  void initState() {
    super.initState();
    bloc.add(LoadProductsEvent());
  }

  @override
  void dispose() {
    super.dispose();
    bloc.close();
    
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Produtos'),
      ),
      body: SafeArea(
        child: SingleChildScrollView(
            child: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Column(
            children: [
              const SizedBox(
                height: 10,
              ),
              const TextField(),
              const TitleSection(title: 'Categorias'),
              Container(
                  margin: const EdgeInsets.all(10),
                  height: 120,
                  child: ListView(
                    scrollDirection: Axis.horizontal,
                    children: [
                      ButtonMenu(
                          action: () {},
                          buttonName: 'Vestuário',
                          icon: Icons.store_mall_directory_rounded),
                      ButtonMenu(
                          action: () {},
                          buttonName: 'Jogos',
                          icon: Icons.sports_esports_outlined),
                      ButtonMenu(
                          action: () {},
                          buttonName: 'Vouchers',
                          icon: Icons.feed_outlined),
                      ButtonMenu(
                          action: () {},
                          buttonName: 'Moskelines',
                          icon: Icons.menu_book_outlined),
                      ButtonMenu(
                          action: () {},
                          buttonName: 'Blusas',
                          icon: Icons.paid_outlined),
                    ],
                  )),
              Container(
                margin: const EdgeInsets.all(10),
                height: MediaQuery.of(context).size.height,
                child: BlocBuilder<ProductsBloc, ProductsState>(
                  bloc: bloc,
                  builder: (context, state) {
                    final state = bloc.state;

                    if (state is ProductInicialState) {
                      return const Center(
                        child: CircularProgressIndicator(),
                      );
                    } else if (state is ProductSuccessState) {
                      final productsList = state.products;
                      return GridView.builder(
                        gridDelegate:
                            const SliverGridDelegateWithFixedCrossAxisCount(
                          childAspectRatio: 0.7,
                          crossAxisCount: 2,
                          crossAxisSpacing: 10,
                          mainAxisSpacing: 10,
                        ),
                        itemCount: productsList.length,
                        itemBuilder: (context, index) {
                          final item = productsList[index];
                          return ProductDisplay(
                              productEntity: productsList[index],
                              icon: Icons.store_mall_directory_rounded,
                              productName: item.productName,
                              action: () {});
                        },
                      );
                    } else {
                      return Container();
                    }
                  },
                ),
              ),
              const TitleSection(title: 'Produtos'),
            ],
          ),
        )),
      ),
    );
  }
}

我的Bloc代码如下:

import 'package:bloc/bloc.dart';

import 'package:ConfidentialName/domain/usecases/get_all_products_usecase.dart';

import 'products_event.dart';
import 'products_state.dart';

class ProductsBloc extends Bloc<ProductsEvent, ProductsState> {
  final GetAllProductsUsecase usecase;

  ProductsBloc(
    this.usecase,
  ) : super(ProductInicialState()) {
    on<LoadProductsEvent>((event, emit) async {
      final result = await usecase.getAllProducts();
      result.fold((l) => emit.call(ProductErrorState(l)),
          (list) => emit.call(ProductSuccessState(list)));
    });
  }
}

我不明白为什么会出现这个错误。

2个回答

11

在发出状态之前,只需检查区块是否已关闭。

if(isClosed) return; // Here
result.fold((l) => emit.call(ProductErrorState(l)),
          (list) => emit.call(ProductSuccessState(list)));

如果你想要发出状态,请确保你没有销毁 bloc,

可以按照以下方式初始化 bloc:

late ProductsBloc bloc;

  @override
  void initState() {
    super.initState();
    bloc = Modular.get<ProductsBloc>();
    bloc.add(LoadProductsEvent());
  }

我使用了你的代码更新了我的代码,但仍然显示相同的错误。:s - WesleyAlmont
3
我之前不知道在 cubits 和 blocs 中有 isClosed 属性 - 我一直在收到错误信息 "Bad state: Cannot emit new states after calling close",因为我的 cubit 中有正在发出的流 - 添加一个 !isClosed 检查解决了这个问题 -- 在这里添加评论是希望 SEO 可以将其他遇到 "Bad state: Cannot emit new states after calling close" 错误的人引导到这个答案。 - kris

3
当您将bloc绑定为Singleton时,可能会出现问题。在app_module文件(依赖注入)中将其更改为Bind.factory。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接