Ответ
Scoped Model — это паттерн управления состоянием, основанный на InheritedWidget. Я использовал его в небольших проектах для простого разделения состояния между виджетами без необходимости прокидывать его через конструкторы.
Как это работает:
- Создаётся модель, расширяющая класс
Model. - Модель помещается в дерево виджетов с помощью
ScopedModel. - Виджеты, которым нужно состояние, оборачиваются в
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 из-за лучшей масштабируемости и тестируемости.