← Назад к вопросам

Можно ли использовать вместе MVVM и BLoC?

2.7 Senior🔥 101 комментариев
#State Management#Архитектура Flutter#ООП и паттерны

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Можно ли использовать MVVM и BLoC вместе?

Короткий ответ: Технически можно, но обычно это плохая идея. Давайте разберёмся почему и когда это может быть оправдано.

Архитектурные различия

BLoC (Business Logic Component)

// BLoC — это паттерн для управления состоянием
class CounterBloc extends Bloc<CounterEvent, CounterState> {
  CounterBloc() : super(CounterInitial());
  
  @override
  Stream<CounterState> mapEventToState(CounterEvent event) async* {
    if (event is IncrementEvent) {
      final currentState = state as CounterState;
      yield CounterState(currentState.count + 1);
    }
  }
}

// Event-driven, реактивный подход

MVVM (Model-View-ViewModel)

// ViewModel — это просто объект, держащий состояние
class CounterViewModel extends ChangeNotifier {
  int _count = 0;
  int get count => _count;
  
  void increment() {
    _count++;
    notifyListeners();
  }
}

// Imperative, явное управление состоянием

Плюсы использования вместе

1. Постепенная миграция

Если переводишь старый MVVM код на BLoC, можно использовать оба параллельно:

class UserScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return BlocBuilder<UserBloc, UserState>(
      builder: (context, blocState) {
        return Consumer<UserViewModel>(
          builder: (context, viewModel, child) {
            // Комбинированная логика
            return Text(blocState.name + viewModel.title);
          },
        );
      },
    );
  }
}

2. Разделение ответственности

MVVM для простой UI логики, BLoC для сложной бизнес-логики:

// BLoC обрабатывает API, валидацию, бизнес-логику
class AuthBloc extends Bloc<AuthEvent, AuthState> { ... }

// ViewModel обрабатывает только UI состояние
class AuthFormViewModel extends ChangeNotifier {
  void updateEmail(String email) {
    // Просто обновить UI
    notifyListeners();
  }
}

3. Тестирование компонентов

Проще тестировать части отдельно.

Минусы использования вместе

1. Путаница в архитектуре (главная проблема)

Когда каждый разработчик по-своему решает, что куда класть:

// Где должна быть логика валидации?
// В BLoC или в ViewModel? 🤔

// Кто отвечает за состояние?
// BLoC state или ViewModel properties?

// Куда добавить новую фичу?
// Непонятно, приводит к дублированию

2. Дублирование состояния

// BLoC state
class UserState {
  final String name;
  final String email;
}

// ViewModel также держит то же состояние
class UserViewModel extends ChangeNotifier {
  String name = '';
  String email = '';
  // Два источника истины — плохо!
}

3. Сложность с синхронизацией

Если оба управляют состоянием, нужно синхронизировать:

class UserBloc extends Bloc<UserEvent, UserState> {
  final UserViewModel viewModel;
  
  @override
  Stream<UserState> mapEventToState(UserEvent event) async* {
    // ...
    yield newState;
    viewModel.sync(newState); // Синхронизация — боль
  }
}

4. Усложнение кода

// Widget должен ждать от обоих
BlocBuilder<UserBloc, UserState>(
  builder: (context, blocState) {
    return Consumer<UserViewModel>(
      builder: (context, viewModel, child) {
        // Вложенность, нечитаемо
        return build(blocState, viewModel);
      },
    );
  },
);

5. Новички путаются ещё больше

Вместо одного паттерна нужно знать два, и решить когда использовать каждый.

Когда это может быть оправдано

✅ Постепенная миграция с BLoC

Если проект на MVVM и вы переходите на BLoC. Делайте это постепенно, модуль за модулем. Не смешивайте на одном экране.

✅ Микроскопный микс

Используйте MVVM для очень простых UI элементов (форма с валидацией) и BLoC для сложной бизнес-логики. Но четко разделите ответственность.

// BLoC для бизнес-логики (запросы, валидация)
class LoginBloc extends Bloc<LoginEvent, LoginState> { ... }

// ViewModel только для UI состояния (фокус на поле, видимость пароля)
class LoginFormViewModel extends ChangeNotifier {
  bool _showPassword = false;
  void toggleShowPassword() {
    _showPassword = !_showPassword;
    notifyListeners();
  }
}

Рекомендация

Лучше выбрать ОДНУ архитектуру и придерживаться её.

Выбор между ними:

  • BLoC — для больших проектов, сложной логики, когда критична testability
  • MVVM — для простых приложений, быстрого прототипирования
  • Provider + ChangeNotifier — компромисс, проще чем BLoC
  • Riverpod — современная альтернатива BLoC с меньшим overhead

Смешивание двух паттернов добавляет сложность, запутанность и потенциальные баги, при этом не давая значимых преимуществ. Выбирай одну, используй её правильно, все будут счастливы.

Можно ли использовать вместе MVVM и BLoC? | PrepBro