Optimiza la carga de flows y paywalls en el SDK de Android

Una carga fiable de un flow o paywall en Android hace tres cosas: renderiza rápido, devuelve la variación orientada a la audiencia y recurre al respaldo de forma elegante cuando la red es lenta. Las reglas que se describen a continuación cubren los patrones de timing, caché y respaldo para conseguirlo.

Tip

Las reglas asumen que Adapty.activate() y Adapty.identify() ya se han resuelto. Consulta Orden de llamadas en el SDK de Android.

Reglas y errores comunes

Haz estoNo hagas estoPor qué
Obtén el placement que vas a mostrar, o precalienta la caché con preloadFlows (SDK 4.1+).Lanza tus propias llamadas concurrentes a getFlow al iniciar.Un burst de prefetch manual bloquea el hilo principal y produce una pantalla en negro. preloadFlows está diseñado para esto y ejecuta el lote de forma concurrente.
Llama a getFlow después de que la atribución haya tenido tiempo de resolverse — por ejemplo, 1–2 segundos después de activate o tras el disparo de setOnProfileUpdatedListener.Llama a getFlow en Application.onCreate().La atribución aún no ha llegado. El flow se resuelve contra la audiencia por defecto y omite silenciosamente los segmentos y la personalización de ASA.
Configura un loadTimeout y un paywall de respaldo para cada placement.Esperes a getFlow indefinidamente.Sin un timeout, los usuarios con mala conectividad ven una pantalla en blanco hasta que la red responde — o cierran la app.

Consulta Obtener paywalls y productos para la referencia de parámetros fetchPolicy y loadTimeout, y Placements para elegir el placement adecuado.

Precargar placements

Info

preloadFlows y preloadFlowsForDefaultAudience están disponibles a partir de la versión 4.1 del SDK.

preloadFlows almacena en caché el JSON del flow con antelación — una solicitud por placement. Luego se usa de forma habitual: getFlow para el flow y getFlowConfiguration para su configuración de vista.

fetchPolicy decide qué capa lee primero un getFlow posterior, no si puede acceder a la caché en absoluto:

  • ReturnCacheDataElseLoad lee primero la copia precargada y solo va a la red si no hay nada en caché. ReturnCacheDataIfNotExpiredElseLoad(maxAgeMillis) hace lo mismo mientras la copia sea más reciente que maxAgeMillis.
  • El valor predeterminado, ReloadRevalidatingCacheData, va primero a la red y usa la copia precargada como respaldo cuando la petición falla o se agota el tiempo de espera.

Una precarga resulta útil en ambos casos, pero de forma distinta: una política de caché primero elimina la petición, mientras que el valor predeterminado la mantiene y obtiene una copia en caliente como respaldo.

Úsalo cuando sepas qué placements necesitará la sesión pero no quieras mostrarlos todavía — por ejemplo, justo después de que se resuelvan activate e identify, para el flow detrás de un botón que el usuario aún no ha pulsado.

Parámetros:

  • placementIds (obligatorio): los placements a precargar. Los IDs en blanco o duplicados se ignoran.
  • loadTimeout (opcional): tiempo de espera aplicado a cada placement individualmente, no al lote completo. Por defecto es 5 segundos; los valores inferiores a 1 segundo se elevan a 1 segundo.

Aspectos importantes del comportamiento:

  • La llamada de retorno se activa solo después de que se hayan intentado todos los placements, e informa los fallos por placement juntos. Un fallo en un placement no detiene los demás.
  • Si un placement supera el tiempo de espera, encuentra un error de servidor o falla por un error de red, el SDK recurre a las variaciones de respaldo para ese placement. Los demás fallos se informan tal cual.
  • La precarga solo calienta la caché. No devuelve contenido: igualmente debes llamar a getFlow para mostrarlo.

Qué cubre una precarga

Un flow llega a la pantalla en capas. Una precarga cubre la primera, exactamente igual que getFlow:

CapaObtenida porPreparada por una precarga
JSON del flow — la variación elegida, sus IDs de producto y el Remote ConfiggetFlowSí
Diseño de interfaz — estructura, estilos y textos de la pantallagetFlowConfigurationNo
Imágenes, incluido el fotograma estático que reemplaza a un elemento de vídeogetFlowConfiguration, en segundo planoNo
Archivos de vídeoEl reproductor del sistema, al renderizar la pantallaNo almacenado en caché por el SDK

getFlowConfiguration espera el layout, por lo que la primera solicitud de un layout determinado implica un viaje de ida y vuelta a la red, incluso después de una precarga. El SDK guarda ese layout en su propio caché de disco, que sobrevive a los reinicios de la app y se lee antes de cualquier llamada a la red, de modo que el coste recae en la primera solicitud y no en cada una. Una vez que el SDK tiene el layout, comienza a cachear las imágenes de forma independiente a la llamada: no bloquea la pantalla, y no hay ningún callback ni error que informe de cuándo termina.

Identificar qué placement falló

El callback recibe un AdaptyPreloadPlacementsError que cubre todo el lote, con el código REQUEST_FAILED (2005). Para ver los fallos individuales, lee su propiedad preloadErrors — un mapa con clave por ID de placement:

Adapty.preloadFlows(listOf("onboarding", "main_paywall")) { error ->
    if (error is AdaptyPreloadPlacementsError) {
        error.preloadErrors.forEach { (placementId, placementError) ->
            // log or retry the individual placement
        }
    }
}

preloadErrors existe solo en AdaptyPreloadPlacementsError, así que confirma el tipo primero: cualquier otro AdaptyError proviene de algo distinto a un fallo por placement.

Omitir la segmentación de audiencias

Para calentar la caché sin esperar a la segmentación de audiencias, usa la variante de audiencia predeterminada. No recibe loadTimeout:

Adapty.preloadFlowsForDefaultAudience(listOf("main_paywall")) { error -> }

Mostrar el contenido multimedia de la primera pantalla desde el bundle de la app

Un flow descarga sus imágenes y vídeos desde Adapty. Para mostrar el contenido multimedia de la primera pantalla de forma instantánea, sírvelo desde el bundle de la app. Es una buena forma de reutilizar recursos que ya incluyes en la app, como los visuales de un onboarding nativo existente.

  1. En el Flow & Paywall Builder, asigna un ID de medio personalizado a la imagen o el vídeo. El archivo que subas allí será el de respaldo.
  2. Añade el archivo a la carpeta res/raw o assets de tu app.
  3. Cuando crees la vista del flow con getFlowView, pasa el archivo incluido en el bundle para ese ID en 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,
)

Los archivos incluidos en el paquete aumentan el tamaño de descarga de tu app, así que incluye solo los archivos multimedia que el usuario ve primero.

Los archivos multimedia que no incluyas en el paquete seguirán apareciendo de inmediato: la configuración de la vista lleva una copia de baja resolución de cada imagen, incluido el fotograma estático de los vídeos, y la muestra hasta que se cargue el archivo completo.

Para la referencia completa de customAssets, consulta Personalizar recursos.

Ajusta para conectividad deficiente

Para mercados con conectividad consistentemente deficiente (zonas rurales, transporte público, regiones con problemas de enrutamiento):

  • Establece fetchPolicy en AdaptyPlacementFetchPolicy.ReturnCacheDataElseLoad en cada solicitud excepto la primera.
  • Configura un paywall de respaldo para cada placement en el Adapty Dashboard.
  • Establece loadTimeout entre 3 y 5 segundos y acepta el respaldo cuando se agote el tiempo.
  • No condicionales la visualización del flow a getProfile. Llama a getFlow de forma independiente para que un perfil lento no bloquee la interfaz.