Для чего нужен Scoped Model в Flutter?

«Для чего нужен Scoped Model в Flutter?» — вопрос из категории State Management, который задают на 29% собеседований Flutter Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Scoped Model — это паттерн управления состоянием, основанный на InheritedWidget. Я использовал его в небольших проектах для простого разделения состояния между виджетами без необходимости прокидывать его через конструкторы.

Как это работает:

  1. Создаётся модель, расширяющая класс Model.
  2. Модель помещается в дерево виджетов с помощью ScopedModel.
  3. Виджеты, которым нужно состояние, оборачиваются в ScopedModelDescendant и автоматически перестраиваются при вызове notifyListeners().

Пример из моего опыта — счётчик:

// Модель состояния
class CounterModel extends Model {
  int _count = 0;
  int get count => _count;

  void increment() {
    _count++;
    notifyListeners(); // Уведомляет подписчиков об изменении
  }
}

// В корне приложения
ScopedModel(
  model: CounterModel(),
  child: MyApp(),
);

// Виджет, который использует состояние
ScopedModelDescendant<CounterModel>(
  builder: (context, child, model) {
    return ElevatedButton(
      onPressed: model.increment,
      child: Text('Count: ${model.count}'),
    );
  },
);

Почему я его выбирал:

  • Минимальный boilerplate-код — быстрее начать, чем с Provider или Bloc.
  • Автоматическое обновление UI — не нужно вручную вызывать setState.
  • Простота для небольших приложений — идеально для прототипов или проектов с 2-3 экранами.

Однако для сложных приложений с множеством моделей и бизнес-логикой я переходил на Provider или Riverpod из-за лучшей масштабируемости и тестируемости.