D
BLoC PatternHard50 XP4 min read

How do you implement Bloc-to-Bloc communication?

TL;DR: Never hold a direct reference from one Bloc to another. Instead, use a shared Repository stream (both Blocs listen to the same data source), or inject a StreamController in the shared layer and have Blocs subscribe via emit.forEach().

Full Answer

BlocA calling BlocB.add() directly creates tight coupling and makes testing harder. The correct pattern uses a shared data source as the intermediary.

Recommended Patterns

  • Shared Repository Stream: AuthRepository exposes Stream<AuthEvent>. Both UserBloc and CartBloc subscribe via emit.forEach()
  • RepositoryProvider: Inject the shared repository at the top of the tree. Both Blocs read from it independently
  • Event Bus (avoid in complex apps): Global broadcast stream — hard to trace in larger apps
⚠️

If you find yourself needing to pass BlocA into BlocB's constructor, that's a signal to extract shared logic into a Repository or UseCase layer.

Code Examples

dartTwo Blocs reacting to the same auth stream
Output
// AuthRepository.logout() -> LogoutEvent broadcast
// CartBloc + ProfileBloc both reset independently

Common Mistakes

  • Passing BlocA as a dependency to BlocB — creates circular dependencies and makes testing a nightmare
  • Using a global event bus for fine-grained communication — reserve it for app-wide events like auth changes

Interview Tip

💡

The bloc_bloc team's recommended pattern is shared Repository streams. Show you know this — most candidates say 'just inject the other Bloc' which is the anti-pattern.

#bloc-communication#stream#repository#event-bus