Запросы к бэкенду

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

Виды запросов

Чем запрос отличается от действия

ДействияЗапросы к бэкенду
Что запускаетНажатие, двойное нажатие, долгое нажатие или загрузка страницыОткрытие страницы или появление виджета с запросом
Для чегоПереходы, сообщения, изменение переменных, вызовы API и прочееПолучение данных; в чатах и лентах интерфейс обновляется сам при изменении данных
СколькоНа виджете может быть несколько действийНа виджете или странице — только один запрос
УсловияМогут выполняться по условию
КешированиеРезультат кешируется: меньше обращений к серверу и работа без сети
СостоянияЕсть состояния загрузки и пустого результата
ДанныеТолько получение данных с бэкенда

Индикатор загрузки

Пока запрос выполняется, показывается индикатор загрузки из темы проекта (он меняется в меню навигации > Theme Settings > Design System > Loading Indicator). Для конкретного запроса его можно заменить своим.

Порядок действий:

  1. Убедитесь, что запрос добавлен.
  2. Откройте раздел Backend Query справа и разверните Backend Query Loading Widget.
  3. Задайте Loading Widget Type = Image — или выберите компонент, если индикатор уже собран как компонент.
  4. Включите View in UI Builder, чтобы видеть индикатор прямо на холсте.
  5. Выберите Image Type, добавьте изображение и задайте Padding и Width.
  6. Переключатель Center Image ставит индикатор по центру.
  7. Запустите приложение — при загрузке данных появится ваш индикатор.

Копирование запроса

Иногда нужен почти такой же список: например, все задачи и только выполненные. Сложный запрос проще скопировать, чем собирать заново.

  1. Выделите виджет — ListView, GridView или другой, — где запрос уже добавлен.
  2. Откройте вкладку Backend Query и нажмите Copy.
  3. Выделите виджет, куда нужно перенести запрос, откройте ту же вкладку и нажмите Paste Backend Query.
  4. Нажмите Confirm.

Перенос запроса в родительский виджет

Если один и тот же запрос нужен нескольким виджетам страницы, копировать его — значит слать серверу несколько одинаковых обращений. Вместо этого запрос переносят на общего родителя, а виджеты берут данные из переменной, которую он создаёт.

Нажмите кнопку со стрелкой вверх и выберите родительский виджет, куда перенести запрос.

Виджет пустого списка

Виджет пустого списка показывает сообщение, когда данных нет. Пустой экран без объяснений выглядит как ошибка, а такое сообщение — как ответ.

  1. Убедитесь, что запрос добавлен на прокручиваемый виджет: ListView, GridView, Column, Row, DataTable или StaggeredView.
  2. Выделите этот виджет и включите в панели свойств Show Empty List Widget.
  3. Задайте Widget TypeImage или Component; остальные настройки зависят от выбора.
  4. Включите View in UI Builder, чтобы видеть результат на холсте.
  5. Размер и выравнивание настраиваются там же.

Кеширование запросов

Кеширование сохраняет результат запроса: следующий такой же запрос берёт данные из кеша, а не с сервера.

Это ускоряет приложение, снимает нагрузку с сервера и позволяет что-то показывать без интернета. Магазин, например, кеширует описания, цены и изображения товаров — иначе каждое открытие страницы шло бы за ними на сервер.

заметка

Кеширование работает для всех видов запросов.

совет
Разовый запрос

Для запросов Firebase включите Single Time Query, если данные нужно получить один раз. Иначе запрос работает в реальном времени и обновляется при каждом изменении данных.

Что кешировать

Кеш подходит для данных, которые меняются редко, а читаются часто:

  1. Статические материалы — изображения, видео.
  2. Настройки приложения и параметры системы.
  3. То, что дорого вычислять: сложные отчёты, аналитика.

Что не кешировать

  1. Большие объёмы данных — кеш начнёт мешать, а не помогать.
  2. Чувствительные данные: в кеше до них проще добраться.
  3. Быстро меняющиеся данные — кеш устареет раньше, чем пригодится.
  4. Всё, что должно быть точным в каждый момент времени.

Пример

Разберём приложение со списком сотрудников и карточкой каждого. Данные карточки читают часто, а меняют редко — хороший кандидат на кеширование.

Вот как это выглядит:

заметка

Обратите внимание: индикатор загрузки появляется только при первом запросе. Дальше данные приходят из кеша, и ждать больше не приходится.

Порядок действий:

  1. Добавьте запрос. В примере данные сотрудника берутся из документа Firebase по ссылке, запрос стоит на уровне страницы и помечен как Single Time Query.

example-bq.png

Запрос данных сотрудника по ссылке на документ

  1. Откройте Query Cache Settings и включите Enable Query Caching.
  2. Задайте Scope. При App Level тот же самый запрос на любой странице приложения получит данные из кеша; при Page Level кеш работает только в пределах своей страницы.
  3. Если запрос новый, задайте Query Name. Если вы хотите пользоваться уже существующим кешем, выберите имя из списка.

  1. На этом месте появляется подвох: закешировав данные одного сотрудника, приложение покажет их для всех. Чтобы кеш был отдельным для каждой записи, задайте Unique Key — например, идентификатор сотрудника или ссылку на документ.

Без Unique Key данные путаются

С Unique Key всё на месте

  1. Остаётся вторая проблема: закешированные данные будут показываться и после того, как в базе всё изменилось. Кеш нужно вовремя сбрасывать — свойством Should Override Cache или действием Clear Query Cache.

    1. Свойство Should Override Cache принимает логическое значение. Заведите переменную App State — скажем, isCacheOverride — и укажите её здесь.
    2. Заведите вторую переменную App State — lastCacheTime — со значением по умолчанию «текущее время». В ней будет храниться момент последнего обращения к серверу.

img_3.png

Свойство Should Override Cache, привязанное к переменной App State

  1. Теперь опишем логику, которая при каждой загрузке страницы решает, сбрасывать кеш или нет:

    1. Проверяем, задано ли lastCacheTime; если нет — записываем текущее время.
    2. Создаём кастомное действие, которое проверяет, прошло ли с lastCacheTime больше 30 минут. Тридцать минут здесь взяты для примера — срок жизни кеша выбирают по характеру данных.
    3. Если True:
      1. Обновляем lastCacheTime текущим временем, а isCacheOverride — значением True. Тип обновления — Rebuild Current Page, чтобы запрос выполнился заново и данные обновились.
      2. Здесь же можно вызвать действие Clear Query Cache.
      3. Дальше ждём секунду и возвращаем isCacheOverride в False, чтобы следующие полчаса кеш не сбрасывался при каждом открытии страницы.

заметка

В примере кеш сбрасывается двумя способами сразу — действием Clear Query Cache и свойством Should Override Cache. Обычно надёжнее явное действие; свойство удобно там, где сброс должен происходить по условию.

Кастомная функция для проверки времени:

bool isOverrideCacheAction(DateTime cacheTime) {
  // Add your function code here!
  return DateTime.now().difference(cacheTime).inMinutes > 30;
}

custom-func-cache-override.png

Кастомная функция: прошло ли больше 30 минут с последнего обновления кеша
совет

Для каждой записи стоит держать своё время последнего обновления, иначе общая переменная lastCacheTime будет перезаписываться и часть данных перестанет обновляться. Например, храните список JSON вида:

{ "id": 1, "lastCacheTime": '2023-03-22T14:30:00+00:00', }

Действие Clear Query Cache

Действие сбрасывает кеш запроса — когда данные устарели или их нужно перечитать.

Как добавить:

  1. Выделите виджет — контейнер, кнопку или другой.
  2. В панели свойств выберите Actions. Если действие первое, нажмите + Add Action; иначе — «+» под предыдущим действием и Add Action.
  3. Найдите действие Clear Query Cache (раздел State Management).
  4. Задайте ScopeApp Level или Page Level.
  5. В Query Name укажите имя, заданное при кешировании.
  6. Если при кешировании использовался Unique Key, укажите его же — тогда сбросится кеш только нужной записи.

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

обновлено

ESC