Build video feeds
Copy-ready setups for reels, carousels, and multi-video screens, built on FastPixPlayer, FastPixPlayerPool, ViewPager2, Compose pagers, and RecyclerView.
Build reels, carousels, and multi-video screens in the FastPix Android Player.
These are complete, copy-ready setups for the common ways to show more than one video. They share one rule: whoever shows a video decides nothing about playback. A page or screen binds a player to a PlayerView; the player (or the pool of players) decides what plays and what is prepared next.
Pick the recipe that matches your UI:
Every recipe builds its items the same way:
A. One player with next and previous
One PlayerView, one player, a playlist. PrerenderConfig makes Next / Previous show the entry’s first frame at once instead of a black frame.
The player moves to the next entry by itself when one ends (unless loop is on). Add entries as they load with player.addToPlaylist(moreItems).
B. ViewPager2 with View pages
A reel feed: one page per video, each page its own PlayerView, players from the pool.
Inflating pages from XML instead? Give the PlayerView no android:id, or set retainPlayerOnConfigChange = false on it: every page inflates the same id, and ids are what configuration-change retention keys on.
For a horizontal carousel, use ViewPager2.ORIENTATION_HORIZONTAL, and nothing else changes.
C. ViewPager2 with Compose pages
The same feed where each page is a ComposeView calling your app’s shared player composable. The composable only shows the player it is given.
The pager and activity are exactly as in recipe B.
D. Compose VerticalPager and HorizontalPager
All Compose, no ViewPager2:
Compose disposes pages that leave the pager, so there is no re-attach case to handle here.
E. RecyclerView with PagerSnapHelper
The adapter from recipe B works unchanged. What ViewPager2 did for you (telling the pool which page is current) you do from the snap:
Without the extra layout space a RecyclerView binds the next item only as it scrolls into view, too late to pre-render it.
F. A single video anywhere
A detail screen, a preview, a banner: one player, owned by the screen:
Things every recipe relies on
- Showing a player never releases it. A
PlayerViewreleases only a player it created itself; one you assign stays yours (or the pool’s), however often views detach and re-attach. - Your UI should read the player’s real state. Pool players are stopped outside the pre-render window and reused for other entries without
PlaybackListenerevents. If you draw your own spinner or play button, re-readhasRenderedFirstFrame()andisPlaying()when the engine changes state rather than keeping flags from earlier callbacks. Hide a poster onPlaybackListener.onFirstFrameRendered(). - Listeners may remove themselves inside a callback. A one-shot listener is safe.
- Pre-render counts are a maximum. The device’s decoder limit decides how many entries actually pre-render, and DRM-protected entries are never pre-rendered.
- Analytics counts watched videos only. Add
setAnalyticsConfig(AnalyticsConfig.Builder(workSpaceId).build())to a pool (or a config to a player) and each video the user lands on is one view. Preloaded and pre-rendered entries are not counted.
Frequently asked questions
How do I build a vertical reels feed on Android?
Use FastPixPlayerPool with a pager. For ViewPager2 with View pages, bind each page’s PlayerView to pool.playerAt(position) and call pool.setCurrentIndex(position) when the pager settles (recipe B). For Compose, use VerticalPager and drive pool.setCurrentIndex from the settled page (recipe D). Keep offscreenPageLimit or beyondViewportPageCount at least as large as your pre-render counts.
Do I need to release the players in a feed?
No. The pool owns its players, so don’t release them yourself. Call pool.release() when the screen goes away. A PlayerView releases only a player it created itself; a player you assign from the pool stays the pool’s.
Why is my page showing the wrong or a black video after scrolling?
ViewPager2 re-attaches cached pages without rebinding them, and the pool may have reused a page’s player meanwhile. In onViewAttachedToWindow, compare holder.player (or the view’s current player) with pool.playerAt(position) and rebind if they differ. Also drive your UI from the player’s real state with hasRenderedFirstFrame() and isPlaying().
Does pre-rendering inflate my analytics view counts?
No. Analytics counts a view for each video the user actually lands on. Preloaded and pre-rendered entries off screen are never counted, so pre-rendering does not inflate view counts.
What’s next
- Preload and cache for faster startup for the details behind
PreloadConfig,CacheConfig, andPrerenderConfig. - Play a playlist to drive the list behind your feed.
- Monitor video data to measure engagement across the videos your feed plays.