1"use strict";(globalThis.webpackChunkbambuser_docs||=[]).push([[2999],{43323(e,n,i){i.r(n),i.d(n,{assets:()=>s,contentTitle:()=>d,default:()=>p,frontMatter:()=>r,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"mobileSDK/android/sv-android-preloading","title":"Preloading","description":"Use \'preload: true\' in the Android SDK configuration to pre-render the Shoppable Video player in carousels and feeds. Lifecycle and Compose considerations included.","source":"@site/shoppable-video/mobileSDK/android/preloading.mdx","sourceDirName":"mobileSDK/android","slug":"/mobileSDK/android/mobile-sdk/android/preloading","permalink":"/docs/shoppable-video/mobileSDK/android/mobile-sdk/android/preloading","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"id":"sv-android-preloading","title":"Preloading","description":"Use \'preload: true\' in the Android SDK configuration to pre-render the Shoppable Video player in carousels and feeds. Lifecycle and Compose considerations included.","sidebar_label":"Preloading","slug":"mobile-sdk/android/preloading"},"sidebar":"someSidebars","previous":{"title":"Conversion Tracking","permalink":"/docs/shoppable-video/mobileSDK/android/mobile-sdk/android/tracking"},"next":{"title":"Overview","permalink":"/docs/shoppable-video/mobileSDK/react-native/mobile-sdk/react-native/overview"}}');var t=i(74848),a=i(28453);const r={id:"sv-android-preloading",title:"Preloading",description:"Use 'preload: true' in the Android SDK configuration to pre-render the Shoppable Video player in carousels and feeds. Lifecycle and Compose considerations included.",sidebar_label:"Preloading",slug:"mobile-sdk/android/preloading"},d="Preloading",s={},l=[{value:"When to Use Preloading",id:"when-to-use-preloading",level:2},{value:"Enabling Preload",id:"enabling-preload",level:2},{value:"What Preloading Does",id:"what-preloading-does",level:2},{value:"Compose Lifecycle Considerations",id:"compose-lifecycle-considerations",level:2},{value:"Avoid Preloading Off-Screen Items in Large Lists",id:"avoid-preloading-off-screen-items-in-large-lists",level:3},{value:"Memory Budget",id:"memory-budget",level:3},{value:"Do Not Preload in Background Tabs",id:"do-not-preload-in-background-tabs",level:3},{value:"Next Steps",id:"next-steps",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,a.R)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.header,{children:(0,t.jsx)(n.h1,{id:"preloading",children:"Preloading"})}),"\n",(0,t.jsxs)(n.p,{children:["Setting ",(0,t.jsx)(n.code,{children:'"preload" to true'})," in the configuration map instructs the SDK to initialize the player's internal WebView and begin fetching video metadata before the user interacts with it. The result is a near-instant transition from thumbnail to preview mode."]}),"\n",(0,t.jsx)(n.h2,{id:"when-to-use-preloading",children:"When to Use Preloading"}),"\n",(0,t.jsx)(n.p,{children:"Preloading is most beneficial in layouts where multiple videos are visible at once or where a fast tap-to-play response is critical:"}),"\n",(0,t.jsxs)(n.table,{children:[(0,t.jsx)(n.thead,{children:(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.th,{children:"Use case"}),(0,t.jsx)(n.th,{children:"Recommendation"})]})}),(0,t.jsxs)(n.tbody,{children:[(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["Horizontal carousel (",(0,t.jsx)(n.code,{children:"LazyRow"}),")"]}),(0,t.jsx)(n.td,{children:"Enable \u2014 videos adjacent to the viewport benefit from early init"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsxs)(n.td,{children:["Vertical feed (",(0,t.jsx)(n.code,{children:"LazyColumn"}),")"]}),(0,t.jsx)(n.td,{children:"Enable with care \u2014 preload only visible + immediately adjacent items"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Single-video full-screen embed"}),(0,t.jsx)(n.td,{children:"Optional \u2014 the player is already the primary content"})]}),(0,t.jsxs)(n.tr,{children:[(0,t.jsx)(n.td,{children:"Long list (50+ items)"}),(0,t.jsx)(n.td,{children:"Disable \u2014 preloading all items wastes memory and bandwidth"})]})]})]}),"\n",(0,t.jsx)(n.h2,{id:"enabling-preload",children:"Enabling Preload"}),"\n",(0,t.jsxs)(n.p,{children:["Add ",(0,t.jsx)(n.code,{children:'"preload" to true'})," at the top level of your configuration map:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-kotlin",metastring:'title="VideoConfig.kt"',children:'val videoConfig = mapOf(\n "preload" to true, // enable pre-rendering\n "thumbnail" to mapOf(\n "enabled" to true,\n "showPlayButton" to true,\n ),\n "previewConfig" to mapOf(\n "settings" to "products:true; title: false; actions:1; productCardMode: thumbnail",\n ),\n "playerConfig" to mapOf(\n "buttons" to mapOf("dismiss" to "event"),\n "currency" to "USD",\n ),\n)\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Pass this map to ",(0,t.jsx)(n.code,{children:"BambuserVideoConfiguration"})," as normal:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-kotlin",metastring:'title="Usage"',children:'BambuserVideoConfiguration(\n events = listOf("*"),\n videoType = BambuserVideoAsset.Shoppable(videoId),\n configuration = videoConfig,\n)\n'})}),"\n",(0,t.jsx)(n.h2,{id:"what-preloading-does",children:"What Preloading Does"}),"\n",(0,t.jsxs)(n.p,{children:["When ",(0,t.jsx)(n.code,{children:'"preload" to true'})," is set, the SDK:"]}),"\n",(0,t.jsxs)(n.ol,{children:["\n",(0,t.jsx)(n.li,{children:"Creates and attaches the internal WebView at composable composition time, even before the thumbnail is tapped."}),"\n",(0,t.jsx)(n.li,{children:"Loads the player JavaScript bundle and resolves the video manifest in the background."}),"\n",(0,t.jsx)(n.li,{children:"Keeps the player warm so the first user interaction (tap on thumbnail) skips the initialization step entirely."}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"Without preloading, all of these steps happen after the user taps, adding a visible delay."}),"\n",(0,t.jsx)(n.h2,{id:"compose-lifecycle-considerations",children:"Compose Lifecycle Considerations"}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"GetLShoppableVideoView"})," is a Compose composable, so it follows the standard Compose lifecycle. Keep these points in mind when using preloading:"]}),"\n",(0,t.jsx)(n.h3,{id:"avoid-preloading-off-screen-items-in-large-lists",children:"Avoid Preloading Off-Screen Items in Large Lists"}),"\n",(0,t.jsxs)(n.p,{children:["In a ",(0,t.jsx)(n.code,{children:"LazyColumn"})," or ",(0,t.jsx)(n.code,{children:"LazyRow"}),", Compose only composes items near the viewport. Items scrolled far off-screen are disposed. Do not preload items that are more than one or tw
1o positions outside the visible window \u2014 the composable will be disposed before the preload completes anyway."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-kotlin",metastring:'title="LazyRow carousel \u2014 preload adjacent items only"',children:'LazyRow {\n itemsIndexed(videoIds) { index, videoId ->\n // Only preload the current and immediately adjacent videos\n val shouldPreload = index <= currentIndex + 2\n\n sdk.GetLShoppableVideoView(\n modifier = Modifier\n .width(200.dp)\n .aspectRatio(9f / 16f),\n videoConfiguration = BambuserVideoConfiguration(\n events = listOf("*"),\n videoType = BambuserVideoAsset.Shoppable(videoId),\n configuration = mapOf(\n "preload" to shouldPreload,\n "thumbnail" to mapOf("enabled" to true, "showPlayButton" to true),\n "playerConfig" to mapOf("currency" to "USD"),\n ),\n ),\n videoPlayerDelegate = myDelegate,\n )\n }\n}\n'})}),"\n",(0,t.jsx)(n.h3,{id:"memory-budget",children:"Memory Budget"}),"\n",(0,t.jsxs)(n.p,{children:["Each preloaded player holds a WebView instance in memory. On mid-range devices, keep the number of simultaneously preloaded players to ",(0,t.jsx)(n.strong,{children:"3\u20135"})," to stay within a reasonable memory budget. If your app already uses several WebViews elsewhere, reduce this further."]}),"\n",(0,t.jsx)(n.h3,{id:"do-not-preload-in-background-tabs",children:"Do Not Preload in Background Tabs"}),"\n",(0,t.jsxs)(n.p,{children:["If your app has a tab bar and the video carousel lives on a tab that is not currently visible, skip preloading until the tab becomes active. Use ",(0,t.jsx)(n.code,{children:"LocalLifecycleOwner"})," to detect visibility:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-kotlin",metastring:'title="Lifecycle-aware preload"',children:'@Composable\nfun VideoCarousel(videoIds: List<String>) {\n val lifecycleOwner = LocalLifecycleOwner.current\n var isResumed by remember { mutableStateOf(false) }\n\n DisposableEffect(lifecycleOwner) {\n val observer = LifecycleEventObserver { _, event ->\n isResumed = event == Lifecycle.Event.ON_RESUME\n }\n lifecycleOwner.lifecycle.addObserver(observer)\n onDispose { lifecycleOwner.lifecycle.removeObserver(observer) }\n }\n\n LazyRow {\n items(videoIds) { videoId ->\n val sdk = (LocalContext.current.applicationContext as MyApplication).bambuserSDK\n sdk.GetLShoppableVideoView(\n modifier = Modifier.width(200.dp).aspectRatio(9f / 16f),\n videoConfiguration = BambuserVideoConfiguration(\n events = listOf("*"),\n videoType = BambuserVideoAsset.Shoppable(videoId),\n configuration = mapOf(\n "preload" to isResumed, // only preload while the screen is active\n "thumbnail" to mapOf("enabled" to true, "showPlayButton" to true),\n "playerConfig" to mapOf("currency" to "USD"),\n ),\n ),\n videoPlayerDelegate = myDelegate,\n )\n }\n }\n}\n'})}),"\n",(0,t.jsx)(n.admonition,{type:"tip",children:(0,t.jsx)(n.p,{children:"Test preloading on a mid-range device (e.g. 3 GB RAM), not just a flagship. High-end devices will mask memory issues that surface for a significant portion of your users."})}),"\n",(0,t.jsx)(n.h2,{id:"next-steps",children:"Next Steps"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"/docs/shoppable-video/mobileSDK/android/mobile-sdk/android/setup",children:"Setup"})," \u2014 how to integrate ",(0,t.jsx)(n.code,{children:"GetLShoppableVideoView"})," in your screen."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.a,{href:"/docs/shoppable-video/mobileSDK/android/mobile-sdk/android/configuration-and-functions",children:"Configuration and functions"}
1)," \u2014 full reference for all configuration keys."]}),"\n"]})]})}function p(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(c,{...e})}):c(e)}},28453(e,n,i){i.d(n,{R:()=>r,x:()=>d});var o=i(96540);const t={},a=o.createContext(t);function r(e){const n=o.useContext(a);return o.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function d(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:r(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.