FlutterFlowModel

FlutterFlowModel — абстрактный класс, от которого наследуют все модели: и страниц, и компонентов. Он задаёт единый каркас для состояния и поведения виджета: инициализация, работа с состоянием, освобождение ресурсов.

Сам класс и вспомогательные методы wrapWithModel() и createModel() лежат в файле flutter_flow_model.dart, который FlutterFlow генерирует сам.

Как это выглядит для страницы:

Схема использования FlutterFlowModel в классах виджета и модели страницы

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

Схема связи моделей страницы и вложенного компонента

Дальше — по этапам жизненного цикла.

Инициализация

Модель поднимается ровно один раз и связывается с 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, и модель становится доступна всему поддереву.

перевод официальной документации FlutterFlow

обновлено

ESC