Ответ
В архитектуре на основе BLoC я организую взаимодействие через потоки (Streams) и менеджеры состояний, избегая прямых жестких связей. Вот основные паттерны:
1. Использование BlocListener для реакции на изменения состояния одного блока и вызова событий в другом:
BlocListener<AuthBloc, AuthState>(
listener: (context, authState) {
if (authState is AuthSuccess) {
// При успешной авторизации инициируем загрузку профиля
context.read<UserProfileBloc>().add(LoadUserProfile(authState.userId));
}
},
child: ...
)
2. Общий репозиторий или сервис как источник данных для нескольких блоков:
class DataRepository {
final StreamController<DataEvent> _dataStream = StreamController.broadcast();
Stream<DataEvent> get dataStream => _dataStream.stream;
void updateData(Data newData) {
// Обновление данных...
_dataStream.add(DataUpdated(newData));
}
}
// Несколько блоков могут слушать один и тот же поток из репозитория.
3. Композиция блоков (один блок использует другой):
class CheckoutBloc extends Bloc<CheckoutEvent, CheckoutState> {
final CartBloc cartBloc;
late final StreamSubscription _cartSubscription;
CheckoutBloc(this.cartBloc) : super(CheckoutInitial()) {
// Реагируем на изменения состояния корзины
_cartSubscription = cartBloc.stream.listen((cartState) {
if (cartState is CartLoaded) {
add(CalculateTotal(cartState.items));
}
});
}
@override
Future<void> close() {
_cartSubscription.cancel(); // Важно отписаться
return super.close();
}
}
Ключевой принцип — однонаправленный поток данных. Блоки общаются через события и состояния, а не вызывают методы друг друга напрямую, что сохраняет предсказуемость и упрощает тестирование.