Разработка ленты контента (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 с parallax, SliverPersistentHeader для sticky-хедеров. AutomaticKeepAliveClientMixin в карточках с видео — чтобы плеер не пересоздавался при выходе из вьюпорта.
Автовоспроизведение видео
Главная боль video feed. Нужно воспроизводить видео, которое больше всего видно (наибольшая видимая площадь во вьюпорте), и останавливать остальные.
В React Native: IntersectionObserver-подобная логика через onViewableItemsChanged в FlatList с viewabilityConfig: { itemVisiblePercentThreshold: 60 }. Определяем viewableItems, передаём isActive проп в карточку. В карточке — 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 events. Добавили scrollEventThrottle={32} (30fps для событий скролла), заменили FlatList на FlashList — стабильные 60fps.
Алгоритм ленты и infinite scroll
Лента с бесконечной прокруткой требует обработки нескольких состояний: первичная загрузка (skeleton), подгрузка следующей страницы (footer-индикатор), обновление pull-to-refresh (spinner сверху), пустая лента (empty state с CTA), ошибка загрузки (retry кнопка).
Prefetch: начинаем загружать следующую страницу, когда до конца списка остаётся 3–5 карточек. Не ждём, пока пользователь упрётся в spinner.
Оптимистичные реакции (лайки, репосты): обновляем UI мгновенно, запрос уходит в фоне. При ошибке — rollback с shake animation. Пользователь не ждёт подтверждения от сервера для простых действий.
Типы карточек
| Тип | Технические особенности |
|---|---|
| Фото | Lazy load + placeholder, progressive JPEG через FastImage |
| Видео | Thumbnail до воспроизведения, ExoPlayer / AVPlayer |
| Галерея | Горизонтальный PageView/ViewPager внутри вертикального списка |
| Текст | expandable с «Читать далее» при превышении N строк |
| Ссылка-превью | OGP-данные: изображение, заголовок, домен |
Что входит в работу
- Лента с поддержкой разнородных типов карточек
- Infinite scroll с cursor-based пагинацией
- Pull-to-refresh
- Автовоспроизведение видео по видимости
- Лайки, репосты, закладки с оптимистичными обновлениями
- Skeleton-загрузка для первого рендера
- Алгоритмическая лента или хронологическая — по требованию API
- Prefetch следующей страницы
Сроки
3–5 рабочих дней — зависит от количества типов карточек и наличия видео-контента. Лента только с текстом и фото — 3 дня. С видео и разнородными карточками — 4–5 дней. Стоимость рассчитывается индивидуально.







