Оптимизация загрузки флоу и пейволов в Android SDK
Надёжная загрузка флоу или пейвола на Android решает три задачи: быстрый рендеринг, возврат варианта для целевой аудитории и корректный фолбэк при медленной сети. Правила ниже охватывают тайминг, кэширование и паттерны резервного пейвола для достижения этих целей.
Предполагается, что Adapty.activate() и Adapty.identify() уже выполнены. См. Порядок вызовов в Android SDK.
Правила и подводные камни
| Делайте так | Не делайте так | Почему |
|---|---|---|
Запрашивайте плейсмент перед показом или прогрейте кэш с помощью preloadFlows (SDK 4.1+). | Запускайте собственные параллельные вызовы getFlow при старте. | Самодельный пакетный запрос блокирует главный поток и вызывает чёрный экран. preloadFlows создан именно для этого и выполняет пакет параллельно. |
Вызывайте getFlow после того, как атрибуция успела отработать — например, через 1–2 секунды после activate или после срабатывания setOnProfileUpdatedListener. | Вызывайте getFlow в Application.onCreate(). | Атрибуция ещё не пришла. Флоу разрешается по аудитории по умолчанию и незаметно обходит сегменты и персонализацию ASA. |
Задайте loadTimeout и настройте резервный пейвол для каждого плейсмента. | Ждите ответа getFlow бесконечно. | Без таймаута пользователи с плохим соединением видят пустой экран до восстановления сети — или просто закрывают приложение. |
Подробнее о параметрах fetchPolicy и loadTimeout — в разделе Получение пейволов и продуктов, о выборе подходящего плейсмента — в разделе Плейсменты.
Предзагрузка плейсментов
preloadFlows и preloadFlowsForDefaultAudience доступны начиная с версии SDK 4.1.
preloadFlows кэширует JSON флоу заранее — по одному запросу на плейсмент. Дальше всё работает как обычно: getFlow — для получения флоу, getFlowConfiguration — для конфигурации его представления.
fetchPolicy определяет, из какого слоя последующий getFlow читает данные в первую очередь, но не то, может ли он обратиться к кэшу вообще:
ReturnCacheDataElseLoadсначала читает предзагруженную копию и обращается к сети только если кэш пуст.ReturnCacheDataIfNotExpiredElseLoad(maxAgeMillis)делает то же самое, пока копия не старшеmaxAgeMillis.- По умолчанию используется
ReloadRevalidatingCacheData— сначала идёт запрос в сеть, и лишь при ошибке или таймауте используется предзагруженная копия.
Предзагрузка полезна в обоих случаях, но по-разному: при политике «сначала кэш» запрос к сети не выполняется вовсе, а при политике по умолчанию запрос остаётся, но появляется тёплая копия для отката.
Используйте его, когда вы знаете, какие плейсменты понадобятся в сессии, но ещё не хотите их показывать — например, сразу после того, как разрешатся activate и identify, для флоу за кнопкой, которую пользователь ещё не нажал.
Параметры:
placementIds(обязательный): плейсменты для предзагрузки. Пустые и дублирующиеся ID игнорируются.loadTimeout(необязательный): таймаут, применяемый к каждому плейсменту в пакете, а не ко всему пакету целиком. По умолчанию 5 секунд; значения ниже 1 секунды автоматически повышаются до 1 секунды.
Важное поведение:
- Коллбэк срабатывает только после того, как все плейсменты были обработаны, и сообщает об ошибках по каждому плейсменту вместе. Сбой одного плейсмента не останавливает остальные.
- Если плейсмент превысил время ожидания, вернул серверную ошибку или упал с сетевой ошибкой, SDK переключается на резервные варианты для этого плейсмента. Остальные ошибки передаются как есть.
- Предзагрузка только прогревает кэш. Она не возвращает контент — для отображения вы по-прежнему вызываете
getFlow.
Что охватывает предзагрузка
Флоу доходит до экрана послойно. Предзагрузка охватывает первый слой — ровно так же, как это делает getFlow:
| Слой | Загружает | Прогревается предзагрузкой |
|---|---|---|
| Flow JSON — выбранный вариант, идентификаторы продуктов и Remote Config | getFlow | Да |
| Макет UI — структура, стили и текст экрана | getFlowConfiguration | Нет |
| Изображения, включая стоп-кадр вместо видеоэлемента | getFlowConfiguration, в фоне | Нет |
| Видеофайлы | Системный плеер при отрисовке экрана | Не кешируются SDK |
getFlowConfiguration ожидает загрузки макета, поэтому первый запрос для данного макета требует сетевого обращения даже после предзагрузки. Затем SDK сохраняет макет в собственном дисковом кэше, который сохраняется между перезапусками приложения и читается до любого сетевого запроса — таким образом, стоимость приходится на первый запрос, а не на каждый. Как только SDK получает макет, он начинает кэшировать изображения независимо от вызова: экран не блокируется, и ни колбэка, ни ошибки о завершении этого процесса не поступает.
Узнайте, какой плейсмент завершился с ошибкой
Коллбэк получает AdaptyPreloadPlacementsError, охватывающий весь пакет, с кодом REQUEST_FAILED (2005). Чтобы увидеть отдельные ошибки, прочитайте свойство preloadErrors — это map с ключами по ID плейсмента:
Adapty.preloadFlows(listOf("onboarding", "main_paywall")) { error ->
if (error is AdaptyPreloadPlacementsError) {
error.preloadErrors.forEach { (placementId, placementError) ->
// log or retry the individual placement
}
}
}
preloadErrors существует только в AdaptyPreloadPlacementsError, поэтому сначала убедитесь в типе — любая другая AdaptyError возникла не из-за ошибки на уровне отдельного плейсмента.
Пропуск сегментации аудитории
Чтобы прогреть кэш, не дожидаясь сегментации аудитории, используйте вариант для аудитории по умолчанию. Он не принимает loadTimeout:
Adapty.preloadFlowsForDefaultAudience(listOf("main_paywall")) { error -> }
Показывайте медиа первого экрана из бандла приложения
Флоу загружает изображения и видео из Adapty. Чтобы медиа первого экрана отображалось мгновенно, отдавайте его из бандла приложения. Это удобно, если вы уже поставляете нужные файлы с приложением — например, визуальные материалы существующего нативного онбординга.
- В Flow & Paywall Builder задайте пользовательский медиа ID для изображения или видео. Загруженный там файл остаётся в качестве резервного.
- Добавьте файл в папку
res/rawилиassetsвашего приложения. - При создании представления флоу с помощью
getFlowViewпередайте встроенный файл для этого ID вcustomAssets:
// "welcome_video" is the custom media ID set in the Flow & Paywall Builder
val bundledAssets = AdaptyCustomAssets.of(
"welcome_video" to
AdaptyCustomVideoAsset.file(
FileLocation.fromResId(requireContext(), R.raw.welcome),
preview = AdaptyCustomImageAsset.file(
FileLocation.fromResId(requireContext(), R.drawable.welcome_poster),
),
resolution = AdaptyCustomVideoAsset.Resolution(width = 1080, height = 1920),
),
)
val flowView = AdaptyUI.getFlowView(
activity,
flowConfiguration,
products,
eventListener,
insets,
bundledAssets,
)
Встроенные файлы увеличивают размер загрузки приложения, поэтому встраивайте только те медиафайлы, которые пользователь видит в первую очередь.
Медиафайлы, которые не встроены, всё равно отображаются сразу: конфигурация вида содержит небольшую копию каждого изображения в низком разрешении, включая стоп-кадр видео, и показывает её до загрузки полного файла.
Полное описание customAssets см. в разделе Настройка ресурсов.
Настройка для нестабильного соединения
Для рынков с постоянно слабым интернетом (сельские районы, транспорт, регионы с проблемами маршрутизации):
- Установите
fetchPolicyвAdaptyPlacementFetchPolicy.ReturnCacheDataElseLoadдля всех запросов, кроме самого первого. - Настройте резервный пейвол для каждого плейсмента в дашборде Adapty.
- Установите
loadTimeoutв 3–5 секунд и используйте резервный пейвол при срабатывании таймаута. - Не блокируйте показ флоу на
getProfile. ВызывайтеgetFlowнезависимо, чтобы медленная загрузка профиля не задерживала интерфейс.