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