Розробка стрічки контенту (Feed) в мобільній програмі
Стрічка — це екран, який користувачі бачать найчастіше і з яким взаємодіють під час кожної сесії. Продуктивність тут критична: 60 fps при скролингу через сотні карток з зображеннями, відео, текстом різної довжини. Один неоптимізований рендер — і користувачі сприймають програму як «замерзлу», навіть не розуміючи чому.
Продуктивність рендерингу
React Native FlashList. Стандартний FlatList має відоме обмеження — JS-side recycling. FlashList від Shopify вирішує це через нативний протокол RecyclerListView. Ключові параметри: estimatedItemSize (критичен для продуктивності — встановіть середню висоту картки, інакше початковий layout розраховується невірно), overrideItemLayout для карток з відомими розмірами, drawDistance для управління буфером рендерингу.
Різнотипні картки (фото-пост, відео-пост, блок реклами, історії) потребують getItemType — FlashList створює окремий пул переповторення для кожного типу. Без цього відеоплеєр з картки типу «відео» опиниться в картці типу «текст».
Jetpack Compose LazyColumn. key за id елемента є обов'язковим — без нього Compose не може ефективно порівнювати елементи під час оновлення. contentType аналогічний getItemType. Для зображень — AsyncImage з Coil 2.x з placeholder та error fallback. rememberLazyListState() зберігає позицію скролу при змінах конфігурації.
Flutter SliverList. SliverList.builder всередині CustomScrollView — правильний підхід для стрічок з різноманітним контентом: можна додати SliverAppBar з паралаксом, SliverPersistentHeader для липких заголовків. AutomaticKeepAliveClientMixin в картках з відео — щоб плеєр не переосьовувався при виході з viewport.
Автовідтворення відео
Головна біль відеострічки. Потрібно відтворювати відео, яке найбільше видно (найбільша видима площа у viewport), і зупиняти інші.
У React Native: логіка подібна до IntersectionObserver через onViewableItemsChanged у FlatList з viewabilityConfig: { itemVisiblePercentThreshold: 60 }. Визначте viewableItems, передайте isActive prop у картку. У картці — компонент Video з react-native-video з paused={!isActive}.
На Android — ExoPlayer (Media3) з RecyclerView.OnScrollListener. PlayerView у кожній картці переповторює один екземпляр ExoPlayer через ExoPlayer.Builder().build() на рівні адаптера.
З практики: новинний агрегатор, React Native. Стрічка з 50+ карток, частина з відео. На Android гальмувала при скролингу — FPS падав до 30 на Xiaomi Redmi 9. Профілювали через Android Studio Profiler: основне навантаження на Bridge thread від частих подій onScroll. Додали scrollEventThrottle={32} (30 fps для подій скролу), замінили FlatList на FlashList — стабільні 60 fps.
Алгоритм стрічки та нескінченний скролинг
Стрічка з нескінченною прокруткою потребує обробки декількох станів: початкове завантаження (skeleton), завантаження наступної сторінки (footer-індикатор), оновлення pull-to-refresh (спіннер вгорі), порожня стрічка (empty state з CTA), помилка завантаження (кнопка повтору).
Prefetch: почніть завантажувати наступну сторінку, коли до кінця списку залишилося 3–5 карток. Не чекайте, поки користувач упреться в спіннер.
Оптимістичні реакції (лайки, репости): оновіть UI миттєво, запит йде у фоні. При помилці — откат з shake-анімацією. Користувачі не чекають підтвердження від сервера для простих дій.
Типи карток
| Тип | Технічні особливості |
|---|---|
| Фото | Lazy load + placeholder, progressive JPEG через FastImage |
| Відео | Мініатюра до відтворення, ExoPlayer / AVPlayer |
| Галерея | Горизонтальний PageView/ViewPager всередині вертикального списку |
| Текст | expandable з «Читати далі» при перевищенні N рядків |
| Посилання-превью | OGP-дані: зображення, заголовок, домен |
Обсяг роботи
- Стрічка з підтримкою різнотипних карток
- Нескінченний скролинг з cursor-based пагінацією
- Pull-to-refresh
- Автовідтворення відео за видимістю
- Лайки, репости, закладки з оптимістичними оновленнями
- Skeleton-завантаження для першого рендеру
- Алгоритмічна або хронологічна стрічка — за вимогами API
- Prefetch наступної сторінки
Часові рамки
3–5 робочих днів — залежить від кількості типів карток і наявності відеоконтенту. Стрічка тільки з текстом і фото — 3 дні. З відео і різнотипними картками — 4–5 днів. Вартість розраховується індивідуально.







