FlutterFlowModel
FlutterFlowModel — абстрактный класс, от которого наследуют все модели: и страниц, и компонентов. Он задаёт единый каркас для состояния и поведения виджета: инициализация, работа с состоянием, освобождение ресурсов.
Сам класс и вспомогательные методы wrapWithModel() и createModel() лежат в файле flutter_flow_model.dart, который FlutterFlow генерирует сам.
Как это выглядит для страницы:

А так — когда на странице есть компонент (у каждого компонента тоже своя пара классов):

Дальше — по этапам жизненного цикла.
Инициализация
Модель поднимается ровно один раз и связывается с BuildContext и своим виджетом.
abstract class FlutterFlowModel<W extends Widget> {
// инициализация
bool _isInitialized = false;
void initState(BuildContext context);
void _init(BuildContext context) {
if (!_isInitialized) {
initState(context);
_isInitialized = true;
}
if (context.widget is W) _widget = context.widget as W;
_context = context;
}
Ссылки на виджет и контекст
Модель хранит ссылки на связанный виджет и его BuildContext — например, чтобы читать параметры виджета.
// виджет, с которым связана модель: через него удобно
// добираться, например, до параметров
W? _widget;
W? get widget => _widget;
// контекст, с которым связана модель
BuildContext? _context;
BuildContext? get context => _context;
Приватные поля _widget и _context хранят ссылки, геттеры widget и context дают к ним доступ снаружи.
Освобождение ресурсов
bool disposeOnWidgetDisposal = true;
void dispose();
void maybeDispose() {
if (disposeOnWidgetDisposal) {
dispose();
}
// убираем ссылку на виджет, чтобы сборщик мусора его забрал
_widget = null;
}
disposeOnWidgetDisposal определяет, освобождать ли модель вместе с виджетом. У страниц это true, у компонентов — false: моделями компонентов обычно распоряжается родитель.
maybeDispose() сверяется с этим флагом и убирает ссылку на виджет, чтобы тот попал под сборку мусора.
Уведомления об изменениях
Через эти методы модель сообщает своему виджету или родительской странице, что что-то изменилось.
// обновлять ли содержащую страницу или компонент при изменениях
bool updateOnChange = false;
// что вызвать, когда модель получила обновление
VoidCallback _updateCallback = () {};
void onUpdate() => updateOnChange ? _updateCallback() : () {};
FlutterFlowModel setOnUpdate({
bool updateOnChange = false,
required VoidCallback onUpdate,
}) =>
this
.._updateCallback = onUpdate
..updateOnChange = updateOnChange;
// обновить содержащую страницу
void updatePage(VoidCallback callback) {
callback();
_updateCallback();
}
wrapWithModel()
wrapWithModel() связывает модель с виджетом и его потомками, чтобы те могли читать и менять состояние. Метод оборачивает виджет в Provider, и модель становится доступна всему поддереву.