Запросы к бэкенду
Backend Query выполняется сам, когда пользователь открывает страницу или виджет с этим запросом. Полученные данные доступны любому вложенному виджету.
Виды запросов
- Query Collection or Table — одна запись или список записей из коллекции Firestore либо таблицы Supabase.
- Document from Reference — данные документа по ссылке на него.
- API Call Query — вызов API.
- SQLite Query — выполнение SQL-запроса.
- Algolia Search — поиск через Algolia по коллекции Firestore.
Чем запрос отличается от действия
| Действия | Запросы к бэкенду | |
|---|---|---|
| Что запускает | Нажатие, двойное нажатие, долгое нажатие или загрузка страницы | Открытие страницы или появление виджета с запросом |
| Для чего | Переходы, сообщения, изменение переменных, вызовы API и прочее | Получение данных; в чатах и лентах интерфейс обновляется сам при изменении данных |
| Сколько | На виджете может быть несколько действий | На виджете или странице — только один запрос |
| Условия | Могут выполняться по условию | — |
| Кеширование | — | Результат кешируется: меньше обращений к серверу и работа без сети |
| Состояния | — | Есть состояния загрузки и пустого результата |
| Данные | — | Только получение данных с бэкенда |
Индикатор загрузки
Пока запрос выполняется, показывается индикатор загрузки из темы проекта (он меняется в меню навигации > Theme Settings > Design System > Loading Indicator). Для конкретного запроса его можно заменить своим.
Порядок действий:
- Убедитесь, что запрос добавлен.
- Откройте раздел Backend Query справа и разверните Backend Query Loading Widget.
- Задайте Loading Widget Type = Image — или выберите компонент, если индикатор уже собран как компонент.
- Включите View in UI Builder, чтобы видеть индикатор прямо на холсте.
- Выберите Image Type, добавьте изображение и задайте Padding и Width.
- Переключатель Center Image ставит индикатор по центру.
- Запустите приложение — при загрузке данных появится ваш индикатор.
Копирование запроса
Иногда нужен почти такой же список: например, все задачи и только выполненные. Сложный запрос проще скопировать, чем собирать заново.
- Выделите виджет — ListView, GridView или другой, — где запрос уже добавлен.
- Откройте вкладку Backend Query и нажмите Copy.
- Выделите виджет, куда нужно перенести запрос, откройте ту же вкладку и нажмите Paste Backend Query.
- Нажмите Confirm.
Перенос запроса в родительский виджет
Если один и тот же запрос нужен нескольким виджетам страницы, копировать его — значит слать серверу несколько одинаковых обращений. Вместо этого запрос переносят на общего родителя, а виджеты берут данные из переменной, которую он создаёт.
Нажмите кнопку со стрелкой вверх и выберите родительский виджет, куда перенести запрос.
Виджет пустого списка
Виджет пустого списка показывает сообщение, когда данных нет. Пустой экран без объяснений выглядит как ошибка, а такое сообщение — как ответ.
- Убедитесь, что запрос добавлен на прокручиваемый виджет: ListView, GridView, Column, Row, DataTable или StaggeredView.
- Выделите этот виджет и включите в панели свойств Show Empty List Widget.
- Задайте Widget Type — Image или Component; остальные настройки зависят от выбора.
- Включите View in UI Builder, чтобы видеть результат на холсте.
- Размер и выравнивание настраиваются там же.
Кеширование запросов
Кеширование сохраняет результат запроса: следующий такой же запрос берёт данные из кеша, а не с сервера.
Это ускоряет приложение, снимает нагрузку с сервера и позволяет что-то показывать без интернета. Магазин, например, кеширует описания, цены и изображения товаров — иначе каждое открытие страницы шло бы за ними на сервер.
Кеширование работает для всех видов запросов.
Для запросов Firebase включите Single Time Query, если данные нужно получить один раз. Иначе запрос работает в реальном времени и обновляется при каждом изменении данных.
Что кешировать
Кеш подходит для данных, которые меняются редко, а читаются часто:
- Статические материалы — изображения, видео.
- Настройки приложения и параметры системы.
- То, что дорого вычислять: сложные отчёты, аналитика.
Что не кешировать
- Большие объёмы данных — кеш начнёт мешать, а не помогать.
- Чувствительные данные: в кеше до них проще добраться.
- Быстро меняющиеся данные — кеш устареет раньше, чем пригодится.
- Всё, что должно быть точным в каждый момент времени.
Пример
Разберём приложение со списком сотрудников и карточкой каждого. Данные карточки читают часто, а меняют редко — хороший кандидат на кеширование.
Вот как это выглядит:
Обратите внимание: индикатор загрузки появляется только при первом запросе. Дальше данные приходят из кеша, и ждать больше не приходится.
Порядок действий:
- Добавьте запрос. В примере данные сотрудника берутся из документа Firebase по ссылке, запрос стоит на уровне страницы и помечен как Single Time Query.
- Откройте Query Cache Settings и включите Enable Query Caching.
- Задайте Scope. При App Level тот же самый запрос на любой странице приложения получит данные из кеша; при Page Level кеш работает только в пределах своей страницы.
- Если запрос новый, задайте Query Name. Если вы хотите пользоваться уже существующим кешем, выберите имя из списка.
- На этом месте появляется подвох: закешировав данные одного сотрудника, приложение покажет их для всех. Чтобы кеш был отдельным для каждой записи, задайте Unique Key — например, идентификатор сотрудника или ссылку на документ.
Без Unique Key данные путаются
С Unique Key всё на месте
-
Остаётся вторая проблема: закешированные данные будут показываться и после того, как в базе всё изменилось. Кеш нужно вовремя сбрасывать — свойством Should Override Cache или действием Clear Query Cache.
- Свойство Should Override Cache принимает логическое значение. Заведите переменную App State — скажем, isCacheOverride — и укажите её здесь.
- Заведите вторую переменную App State — lastCacheTime — со значением по умолчанию «текущее время». В ней будет храниться момент последнего обращения к серверу.

-
Теперь опишем логику, которая при каждой загрузке страницы решает, сбрасывать кеш или нет:
- Проверяем, задано ли lastCacheTime; если нет — записываем текущее время.
- Создаём кастомное действие, которое проверяет, прошло ли с lastCacheTime больше 30 минут. Тридцать минут здесь взяты для примера — срок жизни кеша выбирают по характеру данных.
- Если True:
- Обновляем lastCacheTime текущим временем, а isCacheOverride — значением True. Тип обновления — Rebuild Current Page, чтобы запрос выполнился заново и данные обновились.
- Здесь же можно вызвать действие Clear Query Cache.
- Дальше ждём секунду и возвращаем isCacheOverride в False, чтобы следующие полчаса кеш не сбрасывался при каждом открытии страницы.
В примере кеш сбрасывается двумя способами сразу — действием Clear Query Cache и свойством Should Override Cache. Обычно надёжнее явное действие; свойство удобно там, где сброс должен происходить по условию.
Кастомная функция для проверки времени:
bool isOverrideCacheAction(DateTime cacheTime) {
// Add your function code here!
return DateTime.now().difference(cacheTime).inMinutes > 30;
}

Для каждой записи стоит держать своё время последнего обновления, иначе общая переменная lastCacheTime будет перезаписываться и часть данных перестанет обновляться. Например, храните список JSON вида:
{ "id": 1, "lastCacheTime": '2023-03-22T14:30:00+00:00', }
Действие Clear Query Cache
Действие сбрасывает кеш запроса — когда данные устарели или их нужно перечитать.
Как добавить:
- Выделите виджет — контейнер, кнопку или другой.
- В панели свойств выберите Actions. Если действие первое, нажмите + Add Action; иначе — «+» под предыдущим действием и Add Action.
- Найдите действие Clear Query Cache (раздел State Management).
- Задайте Scope — App Level или Page Level.
- В Query Name укажите имя, заданное при кешировании.
- Если при кешировании использовался Unique Key, укажите его же — тогда сбросится кеш только нужной записи.