Ответ
В своих Flutter-проектах я использовал несколько паттернов, выбор которых зависит от масштаба и сложности приложения:
-
Provider + ChangeNotifier: Это был мой основной выбор для средних по сложности коммерческих проектов. Он идеально сочетает простоту и мощность, будучи официально рекомендованным командой Flutter. Я создавал модели, расширяющие
ChangeNotifier, и использовалConsumerилиProvider.ofдля реактивного обновления UI.// Типичная модель в таком подходе class AuthService extends ChangeNotifier { User? _currentUser; User? get currentUser => _currentUser; Future<void> login(String email, String password) async { // ... логика запроса к API _currentUser = fetchedUser; notifyListeners(); // UI, слушающий эту модель, перестроится } } -
BLoC (с библиотекой flutter_bloc): Применял для проектов со сложной бизнес-логикой, где важно чёткое разделение ответственности и тестируемость. Паттерн основан на потоках (
Stream) и концепциях Event -> State.// Простой BLoC для счётчика class CounterBloc extends Bloc<CounterEvent, int> { CounterBloc() : super(0) { on<Increment>((event, emit) => emit(state + 1)); on<Decrement>((event, emit) => emit(state - 1)); } } // В UI: BlocBuilder<CounterBloc, int>(builder: (context, count) => Text('$count')) -
Clean Architecture (с Riverpod): Для одного крупного долгосрочного проекта мы выбрали Clean Architecture, чтобы изолировать бизнес-правила (Domain) от деталей реализации (Data, Presentation). В качестве state-менеджера использовали Riverpod, так как он предоставляет отличную типобезопасность, тестируемость и не зависит от
BuildContext.// Provider в Riverpod (уровень Data/Presentation) final userRepositoryProvider = Provider<UserRepository>((ref) { return UserRepositoryImpl(ref.watch(apiClientProvider)); }); final currentUserProvider = StateNotifierProvider<UserNotifier, User?>((ref) { return UserNotifier(ref.watch(userRepositoryProvider)); }); -
MVVM: Часто реализуется "из коробки" с
ChangeNotifier(как ViewModel) иValueListenableBuilder. Это интуитивно понятный паттерн для разделения UI и логики представления.
Мой общий принцип: начинать с Provider для скорости разработки, а для более сложных сценариев переходить на BLoC или Clean Architecture с Riverpod, чтобы обеспечить долгосрочную поддерживаемость кода.
Ответ 18+ 🔞
Ну вот, сидишь такой, выбираешь себе паттерн для Flutter-проекта, а там их, бля, овердохуища разных. Голова кругом идёт. Но если по чесноку, то всё зависит от того, насколько ты хочешь себе жизнь усложнить.
-
Provider + ChangeNotifier: Это, ёпта, как старый добрый жигуль — простой, надёжный, и если что сломается, чинится одной левой. Я его в коммерческих проектах средней руки юзал. Официально рекомендованный, что уже доверия ебать ноль добавляет. Создаёшь какую-нибудь модель, она уведомляет всех, кто на неё подписан, и UI обновляется. Красота.
// Смотри, как всё просто, даже обезьяна разберётся class AuthService extends ChangeNotifier { User? _currentUser; User? get currentUser => _currentUser; Future<void> login(String email, String password) async { // ... тут ты лезешь в API, как последний маньяк _currentUser = fetchedUser; notifyListeners(); // И все, кто слушал эту модель, сразу перерисовываются } } -
BLoC (с библиотекой flutter_bloc): А вот это уже не жигуль, а какой-нибудь немецкий седан с кучей кнопок. Включаешь его, когда логика в приложении такая хитрая жопа, что без чётких правил не разберёшься. Event -> State, потоки, тестируемость — всё серьёзно. Но и возни с ним, ядрёна вошь, побольше.
// БЛоК для счётчика, чтоб ты понимал масштаб class CounterBloc extends Bloc<CounterEvent, int> { CounterBloc() : super(0) { on<Increment>((event, emit) => emit(state + 1)); on<Decrement>((event, emit) => emit(state - 1)); } } // А в UI уже вешаешь слушателя: BlocBuilder<CounterBloc, int>(builder: (context, count) => Text('$count')) -
Clean Architecture (с Riverpod): Это когда ты уже совсем ебанулся и решил построить космический корабль. Мы так для одного монстра делали, чтобы бизнес-логика жила отдельно ото всего, как монах в пещере. В качестве главного по таблеткам взяли Riverpod — штука мощная, от контекста не зависит, и тестировать её — одно удовольствие.
// Провайдер в Riverpod — выглядит страшно, но работает как швейцарские часы final userRepositoryProvider = Provider<UserRepository>((ref) { return UserRepositoryImpl(ref.watch(apiClientProvider)); }); final currentUserProvider = StateNotifierProvider<UserNotifier, User?>((ref) { return UserNotifier(ref.watch(userRepositoryProvider)); }); -
MVVM: Ну а это классика, которую можно на коленке собрать из того же
ChangeNotifier. ViewModel крутит логикой, View рисует картинки. Всё интуитивно, никакой ебалы с потоками, если не хочешь.
Так что мой совет, чувак: не гонись сразу за сложным. Начни с Provider'а, чтобы быстро вьехать и что-то сделать. А если почувствуешь, что проект разбухает и ты уже сам от себя охуеваешь от количества кода — вот тогда уже смотри в сторону BLoC или той самой чистой архитектуры с Riverpod. Чтобы потом не пришлось всё переписывать с криками «ёб твою мать!».