Daniel Roldán
Daniel Roldán

Reputation: 1556

Unhandled Exception: Bad state: Cannot add new events after calling close - Between screens

I have the next architecture :

ScreenA > ScreenB

/// Here i navigate from ScreenA to ScreenB, so here i create the BlocB that i'm going to use
BlocProvider<BlocB>(
  create: (context) => BlocB(),
  child: const ScreenB(),
),  

ScreenB > ScreenC

await Navigator.of(context).pushReplacementNamed(
  PageNames.screenC,
  arguments: context.read<BlocB>(),
);

/// Here i navigate from ScreenB to ScreenC, so i re-value the BlocB
BlocProvider<BlocB>.value(
  value: (args as BlocB),
  child: const ScreenC(),
),

Here i do the same logic until ScreenD where i'm going to use a BlocListener and do the add event from the BlocB

ScreenC > ScreenD

await Navigator.pushNamed(
  context,
  PageNames.screenD,
  arguments: context.read<BlocB>(),
);

/// Here i navigate from ScreenC to ScreenD, so i re-value the BlocB
BlocProvider<BlocB>.value(
  value: (args as BlocB),
  child: const ScreenD(),
),

The BlocF listener

return BlocListener<BlocF, BlocFState>(
  listener: (context, state) {
     if (state.status.isSuccess) {
        context.read<BlocB>().add(someEvent()); // error
     }
  },
  child: child...

Now, i'm going to use a add event from another Bloc (BlocF for example), now send a status and with its listener, i want to add event from BlocB, but a i have the error :

[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: Bad state: Cannot add new events after calling close

I don't know why if i pass through the screens my Bloc

Upvotes: 1

Views: 558

Answers (1)

krishnaacharyaa
krishnaacharyaa

Reputation: 24940

The error message suggests that the BlocB instance being used in the BlocListener of ScreenF is no longer valid. This can happen if the BlocB instance is closed or disposed of when navigating away from ScreenA, and then trying to use it again in ScreenD.

Possible solutions:
  1. Ensure that the BlocB instance is not closed or disposed of when navigating away from ScreenA by using a BlocProvider that is above the entire navigation stack and not just within the individual screens. This way the same BlocB instance is always available throughout the navigation stack.
  2. Pass the BlocB instance as a constructor argument to the next screen, rather than relying on BlocProvider.value to re-create it.

Upvotes: 2

Related Questions