Перейти к основному содержимому

Сгенерированный код: Страницы

При создании новой страницы в FlutterFlow автоматически генерируются два файла: класс Widget и класс Model. Таким образом, если имя созданной страницы — ProductListPage, бэкенд генерации FlutterFlow автоматически создаст класс ProductListPageWidget и класс ProductListPageModel.

Предварительные требования

В этом руководстве используются примеры из сгенерированного кода демонстрационного приложения EcommerceFlow. Чтобы просмотреть сгенерированный код напрямую, ознакомьтесь с репозиторием на GitHub.

Класс PageModel

Классы PageModel отвечают за управление состоянием отдельных страниц и инициализацию компонентов, используемых на этих страницах. Эти классы расширяют класс FlutterFlowModel, который обеспечивает единообразную структуру и общую функциональность для всех моделей страниц.

На следующей диаграмме показано, как FlutterFlow генерирует модель и класс виджета при создании новой страницы в FlutterFlow: page-generation-initial.png

Модель FlutterFlow

Чтобы узнать больше об утилитарных классах и методах, которые FlutterFlow генерирует для всех страниц и компонентов, см. документ FlutterFlowModel.

Управление локальным состоянием

Класс PageModel обычно содержит поля локального состояния, специфичные для страницы, которые соответствуют переменным состояния страницы.

Например, на странице ProductListPage пользователь может создать переменную состояния страницы с именем searchString. Соответственно, в файле product_list_page_model.dart файл (который является файлом Model для ProductListPage), соответствующее поле состояния будет _searchString. Это приватное поле хранит текущую строку поиска и включает геттер и сеттер для управления его значением с логированием любых изменений.

String? _searchString;
set searchString(String? value) {
_searchString = value;
debugLogWidgetClass(rootModel);
}
String? get searchString => _searchString;
Приватные переменные в Dart

В Dart переменные, начинающиеся с подчёркивания (_), такие как _searchString, являются приватными для класса. Это означает, что они не могут быть доступны за пределами класса или его области видимости.

Помимо управления локальным состоянием, данный класс PageModel также содержит поля для обработки состояния виджетов на странице. Например, _dropDownValue — это приватное поле, которое хранит текущее значение виджета выпадающего списка (если он добавлен на текущую страницу). Аналогично _searchString, у него есть геттер и сеттер, которые логируют изменения этого поля.

String? _dropDownValue;
set dropDownValue(String? value) {
_dropDownValue = value;
debugLogWidgetClass(rootModel);
}
String? get dropDownValue => _dropDownValue;

Инициализация моделей дочерних компонентов

Класс PageModel также отвечает за инициализацию моделей компонентов, используемых на странице. Например, если на странице есть компонент CartCounter, модель для этого компонента инициализируется внутри класса модели страницы.

// Model for CartCounter component.
late CartCounterModel cartCounterModel;

@override
void initState(BuildContext context) {
cartCounterModel = createModel(context, () => CartCounterModel()..parentModel = this);

}
к сведению

Внутри класса модели страницы или родительской модели инициализируется только класс модели дочернего компонента. В случае классов моделей страниц они инициализируются внутри самого класса состояния виджета. Подробнее см. в разделе о классе виджета.

При работе с динамическими списками компонентов, такими как в виджете ListView, Row или Column, PageModel инициализирует Map<String, FlutterFlowModel> для управления состоянием каждого экземпляра компонента. Например, если на странице есть список компонентов CategoryAvatar, инициализация может выглядеть так:

// Models for CategoryAvatar dynamic component.
Map<String, FlutterFlowModel> categoryAvatarModels = {};

dispose()

Наконец, функция dispose в классе ProductListPageModel используется для очистки ресурсов, когда они больше не нужны. Это распространённая практика в Flutter для предотвращения утечек памяти. В этом классе функция dispose переопределена для освобождения cartCounterModel, searchQueryFocusNode и searchQueryTextController.


@override
void dispose() {
cartCounterModel.dispose();
searchQueryFocusNode?.dispose();
searchQueryTextController?.dispose();
}

Класс PageWidget

Классы PageWidget отвечают за создание пользовательского интерфейса отдельных страниц и хранение дерева виджетов, спроектированного на холсте FlutterFlow. Эти классы всегда расширяют класс StatefulWidget из Flutter, используя встроенное управление состоянием Flutter через setState для обработки динамических обновлений и взаимодействия с жизненным циклом приложения.

class ProductListPageWidget extends StatefulWidget {
const ProductListPageWidget({super.key});

@override
State<ProductListPageWidget> createState() => _ProductListPageWidgetState();
}

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

Внутри класса State инициализируется объект PageModel. Этот класс служит централизованным местом для управления состоянием страницы, обработки бизнес-логики и взаимодействия со слоем данных.

class _ProductListPageWidgetState extends State<ProductListPageWidget> {
late ProductListPageModel _model;

@override
void initState() {
super.initState();
_model = createModel(context, () => ProductDetailPageModel());

}

Освобождение PageModel

Аналогично, метод dispose класса PageModel вызывается из переопределённого метода dispose класса State виджета. Это гарантирует, что любые ресурсы, управляемые PageModel, такие как прослушиватели или контроллеры, правильно освобождаются при удалении виджета из дерева виджетов.

  @override
void dispose() {
_model.dispose();
super.dispose();
}

Глобальный ключ Scaffold

Каждая страница включает GlobalKey для Scaffold, который можно использовать для управления состоянием scaffold, например для программного открытия или закрытия ящиков или снэкбаров.

final scaffoldKey = GlobalKey<ScaffoldState>();

return Scaffold(
key: scaffoldKey,
...)

Скрытие клавиатуры

Кроме того, корневой виджет каждой страницы — это GestureDetector с обратным вызовом onTap, который снимает фокус с текущего поля ввода. Такой подход гарантирует, что касание в любом месте за пределами поля ввода скрывает клавиатуру или снимает фокус, обеспечивая лучший пользовательский опыт.

return GestureDetector(
onTap: () {
FocusScope.of(context).unfocus();
FocusManager.instance.primaryFocus?.unfocus();
},
...)

Эти функции автоматически добавляются FlutterFlow для обеспечения бесперебойной навигации и правильной обработки клавиатуры на всех страницах.

Действие onPageLoad: Сгенерированный код

При определении действий для триггера действия onPageLoad страницы эти действия добавляются внутри метода addPostFrameCallback в методе initState страницы. Это гарантирует, что действия on Page Load выполняются после того, как виджет полностью собран и отображен. Такой подход позволяет избежать проблем, возникающих при попытке обновить пользовательский интерфейс до его готовности.

 @override
void initState() {
super.initState();
_model = createModel(context, () => ProductListPageModel());

// On page load action.
SchedulerBinding.instance.addPostFrameCallback((_) async {
_model.searchString = null;
safeSetState(() {});
... // more actions
});

}
Безопасный Set State

Метод safeSetState — это пользовательская реализация, построенная поверх метода setState из Flutter. Он гарантирует, что setState вызывается только когда виджет в настоящее время смонтирован, предотвращая потенциальные ошибки во время выполнения.