Оптимизация загрузки флоу и пейволов в React Native SDK

Надёжная загрузка флоу или пейвола в React Native решает три задачи: быстрый рендеринг, возврат варианта, соответствующего аудитории, и корректный резервный сценарий при медленном интернете. Правила ниже охватывают тайминг, кэширование и паттерны резервного отображения.

Tip

Предполагается, что adapty.activate() и adapty.identify() уже выполнились. См. Порядок вызовов в React Native SDK.

Правила и подводные камни

Делайте такНе делайте такПочему
Загружайте конкретный плейсмент или прогревайте кеш с помощью preloadFlows (SDK 4.3.0+).Самостоятельно запускайте параллельные вызовы getFlow при старте.Самодельный prefetch-burst блокирует JS-поток и вызывает чёрный экран. preloadFlows создан для этой задачи и отправляет батч в нативный SDK одним вызовом.
Вызывайте getFlow после того, как атрибуция успела разрешиться — например, через 1–2 секунды после activate или после срабатывания onLatestProfileLoad.Вызывайте getFlow при монтировании корневого компонента.Атрибуция ещё не получена. Флоу разрешится по аудитории по умолчанию и молча обойдёт сегменты и персонализацию ASA.
Задайте loadTimeoutMs и настройте резервный пейвол для каждого плейсмента.Ждите завершения getFlow бесконечно.Без таймаута пользователи с плохим соединением видят пустой экран до тех пор, пока сеть не ответит, — или закрывают приложение.

См. Получение пейволов и продуктов для справки по параметрам fetchPolicy и loadTimeoutMs, а также Плейсменты для выбора подходящего плейсмента.

Предзагрузка плейсментов

Info

preloadFlows и preloadFlowsForDefaultAudience доступны начиная с SDK версии 4.3.0.

preloadFlows заранее кэширует JSON флоу — один запрос на плейсмент. Дальше всё работает как обычно: getFlow для получения флоу, createFlowView для его отображения.

fetchPolicy определяет, из какого слоя последующий getFlow читает данные в первую очередь, но не ограничивает доступ к кэшу как таковому:

  • 'return_cache_data_else_load' сначала читает предзагруженную копию и обращается к сети только при отсутствии кэша. 'return_cache_data_if_not_expired_else_load' делает то же самое, пока копия не старше maxAgeSeconds.
  • Значение по умолчанию, 'reload_revalidating_cache_data', сначала идёт в сеть и использует предзагруженную копию, если запрос завершился с ошибкой или истекло время ожидания.

Предзагрузка даёт выигрыш в любом случае, но по-разному: политика «кэш первым» полностью устраняет запрос, тогда как политика по умолчанию сохраняет его, но получает тёплую копию в качестве запасного варианта.

Используйте это, когда вы знаете, какие плейсменты понадобятся в сессии, но не хотите показывать их сразу — например, сразу после того, как выполнятся activate и identify, для флоу за кнопкой, которую пользователь ещё не нажал.

try {
  await adapty.preloadFlows(['onboarding', 'main_paywall'], {
    loadTimeoutMs: 5000,
  });
} catch (error) {
  // at least one placement failed to preload
}

// Later, when the user reaches the paywall:
const flow = await adapty.getFlow('main_paywall', {
  fetchPolicy: 'return_cache_data_else_load',
});

Параметры:

  • placementIds (обязательный): плейсменты для предзагрузки.
  • loadTimeoutMs (необязательный): таймаут в миллисекундах. По умолчанию 5000; значения ниже 1000 поднимаются до 1000. На iOS таймаут применяется ко всему пакету, на Android — к каждому плейсменту отдельно.

Важные особенности поведения:

  • Промис отклоняется только после того, как будут обработаны все плейсменты, а ошибка агрегирует сбои по каждому из них. Сбой одного плейсмента не останавливает остальные, и плейсменты, которые успешно загрузились, остаются в кеше.
  • Если плейсмент превысил время ожидания или завершился с сетевой ошибкой, SDK использует вариацию аудитории по умолчанию для этого плейсмента. Остальные сбои передаются как есть.
  • Предзагрузка только прогревает кеш. Она не возвращает контент — для отображения по-прежнему нужно вызвать getFlow.

Что покрывает предзагрузка

Флоу появляется на экране послойно. Предзагрузка покрывает первый слой — точно так же, как getFlow:

СлойЗагружается черезПрогревается предзагрузкой
Flow JSON — выбранный вариант, идентификаторы продуктов и Remote ConfiggetFlowДа
UI-макет — структура экрана, стили и текстcreateFlowViewНет
Изображения, включая стоп-кадр вместо видеоэлементаcreateFlowView, в фонеНет
ВидеофайлыСистемный плеер, при рендеринге экранаSDK не кэширует

Таким образом, первый вызов createFlowView для конкретного лейаута всё равно требует одного сетевого запроса даже после предзагрузки. SDK затем сохраняет этот лейаут в своём дисковом кэше, который переживает перезапуски приложения, — так что расходы приходятся только на первый запрос, а не на каждый.

Пропуск сегментации аудитории

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

await adapty.preloadFlowsForDefaultAudience(['main_paywall']);

Показ медиа первого экрана из бандла приложения

Флоу загружает изображения и видео из Adapty. Чтобы медиа первого экрана отображалось мгновенно, раздавайте его из бандла приложения. Это удобно, если нужные ресурсы уже есть в приложении — например, визуалы существующего нативного онбординга.

  1. В Flow & Paywall Builder задайте пользовательский медиаидентификатор для изображения или видео. Файл, загруженный туда, остаётся как запасной вариант.
  2. Добавьте файл в нативные проекты: в бандл iOS-приложения и в папку assets Android.
  3. При создании представления флоу передайте бандловый файл для этого идентификатора в customAssets:
// "welcome_video" is the custom media ID set in the Flow & Paywall Builder
const bundledAssets: Record<string, AdaptyCustomAsset> = {
  'welcome_video': {
    type: 'video',
    fileLocation: {
      ios: { fileName: 'welcome.mp4' },
      android: { relativeAssetPath: 'videos/welcome.mp4' },
    },
  },
};

const view = await createFlowView(flow, { customAssets: bundledAssets });

Файлы, добавленные в бандл, увеличивают размер загрузки приложения, поэтому включайте в него только медиа, которое пользователь видит первым.

Медиафайлы, которые вы не включаете в бандл, всё равно появляются сразу: в макете флоу содержится небольшая копия каждого изображения в низком разрешении, включая стоп-кадр видео, и она отображается до загрузки полного файла.

Полный справочник по customAssets см. в разделе Настройка ресурсов.

Настройка для нестабильного соединения

Для рынков с постоянно плохим соединением (сельские районы, транспорт, регионы с проблемами маршрутизации):

  • Устанавливайте fetchPolicy: 'return_cache_data_else_load' на каждый запрос, кроме самого первого.
  • Настройте резервный пейвол для каждого плейсмента в дашборде Adapty.
  • Устанавливайте loadTimeoutMs в 3–5 секунд и принимайте резервный пейвол при срабатывании таймаута.
  • Не делайте отображение флоу зависимым от getProfile(). Вызывайте getFlow независимо, чтобы медленный профиль не блокировал интерфейс.