Flutter bloc Cubit Bad state: Cannot emit new states after calling close

Issue

I have an app that I build using Cubit
I have two pages A and B.every thing works fine on its own. I use a change status cubit on both pages but when I move to the second page and pop to return to the first page I see the error on the title.
I inject dependencies using get it

route A

routes: {
        '/home': (context) => MultiBlocProvider(providers: [
              BlocProvider<ChangeStatusCubit>(
                create: (context) => locator<ChangeStatusCubit>(),
              ),
            ], child: const TodoHomePage()),

Route B

'/details': (context) => MultiBlocProvider(
            providers: [
              BlocProvider<ChangeStatusCubit>(
                create: (context) => locator<ChangeStatusCubit>(),
              ),
            ],
            child: TodoDetailsPage(),

dependency injection

locator.registerLazySingleton<ChangeStatusCubit>(() => ChangeStatusCubit(
        locator(),
      ));

cubit

changeStatus(int id) async {
    emit(ChangeStatusLoading());
    try {
      ResponseModel response = await _changeStatusUseCase(id);
      if (response.status == 200) {
        emit(ChangeStatusLoaded(response.data));
      } else {
        emit(ChangeStatusError(response.error?.todo?.first ?? ""));
      }
    } catch (e) {
      emit(ChangeStatusError(e.toString()));
    }
  }

Solution

When you use create to initialize the BlocProvider‘s bloc, the bloc’s stream will be closed when that BlocProvider is unmounted.

To solve this, you can either move your BlocProvider higher up in the widget tree, so that it will remain mounted between pages, or you can use the BlocProvider.value constructor.

The latter is probably best, since you aren’t actually creating a bloc, but making use of a pre-existing singleton. Though it would also make sense to move the widget higher up, so that it’s a parent of the Navigator – that way you can declare it just once and reduce code duplication.

However, keeping the structure in your example, your code might look something like this:

routes: {
    '/home': (context) => MultiBlocProvider(
        providers: [
            BlocProvider.value<ChangeStatusCubit>(
                value: locator<ChangeStatusCubit>(),
            ),
        ],
        child: const TodoHomePage(),
    ),
    '/details': (context) => MultiBlocProvider(
        providers: [
            BlocProvider<ChangeStatusCubit>.value(
                value: locator<ChangeStatusCubit>(),
            ),
        ],
        child: TodoDetailsPage(),
    ),
}

Answered By – Michael Horn

Answer Checked By – Marie Seifert (FlutterFixes Admin)

Leave a Reply

Your email address will not be published. Required fields are marked *