Розробка стрічки підписок (Following Feed) в мобільному додатку

TRUETECH займається розробкою, підтримкою та обслуговуванням мобільних додатків iOS, Android, PWA. Маємо великий досвід та експертизу для публікації мобільних додатків до популярних маркетів Google Play, App Store, Amazon, AppGallery та інші.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1735 послуг
Розробка стрічки підписок (Following Feed) в мобільному додатку
Середній
~2-3 дні
Часті запитання

Наші компетенції:

Етапи розробки

Останні роботи

  • image_mobile-applications_feedme_467_0.webp
    Розробка мобільного додатка для компанії FEEDME
    792
  • image_mobile-applications_xoomer_471_0.webp
    Розробка мобільного додатку для компанії XOOMER
    671
  • image_mobile-applications_rhl_428_0.webp
    Розробка мобільного додатку для компанії RHL
    1097
  • image_mobile-applications_zippy_411_0.webp
    Розробка мобільного додатку для компанії ZIPPY
    969
  • image_mobile-applications_affhome_429_0.webp
    Розробка мобільного додатку для компанії Affhome
    914
  • image_mobile-applications_flavors_409_0.webp
    Розробка мобільного додатку для компанії FLAVORS
    495

Розробка ленти підписок (Following Feed) в мобільній програмі

Лента підписок — технічно найскладніший компонент соціальної програми. Не тому що написати SELECT posts WHERE author_id IN (following_ids) ORDER BY created_at DESC складно — це працює до ~10K користувачів. Проблема починається коли потрібно тримати ленту актуальною в реальному часі, обробляти «знаменитостей» з мільйоном підписчиків у feed, і відправляти перший екран швидко.

Fan-out vs Fan-in: вибір архітектури

Два класичних підходи до формування ленти:

Fan-out on write (push) Fan-in on read (pull)
Принцип При публікації пишемо в ленти всіх підписчиків При запиті ленти збираємо з підписок
Плюси Читання швидке (готова лента в Redis) Немає дублювання даних, простіше для «зірок»
Мінуси Запис дорога для популярних авторів Читання повільніше, складніше ранжування
Коли До ~100K підписчиків у автора Автори з мільйонами фолловерів

Більшість програм використовує гібрид: fan-out для звичайних користувачів, fan-in для «зірок» (>50K підписчиків). Порог настоюється.

Для MVP — fan-in достатньо:

SELECT p.*, u.name, u.avatar_url
FROM posts p
JOIN follows f ON p.author_id = f.followee_id
JOIN users u ON p.author_id = u.id
WHERE f.follower_id = :user_id
  AND p.created_at < :cursor
ORDER BY p.created_at DESC
LIMIT 20;

Індекси: follows(follower_id), posts(author_id, created_at DESC).

Realtime-обновлення

Три варіанти:

Pull to refresh — користувач тягне вниз, запитуємо пости новіші за firstPost.created_at. Найпростіший варіант, працює везде.

WebSocket/SSE — сервер пушить нові пости клієнту. При отриманні показуємо баннер «N нових постів» вгорі ленти (як Twitter). Клієнт не вставляє їх автоматично — тільки по тапу на баннер, інакше лента прискочує під пальцем.

Long polling — компроміс без WebSocket.

На iOS WebSocket — URLSessionWebSocketTask. На Android — OkHttp WebSocket. На Flutter — web_socket_channel.

Пагінація та cursor

Обов'язково cursor-based, не OFFSET:

  • cursor = created_at останнього поста на поточній сторінці (ISO 8601 string)
  • Запит: GET /feed?cursor=2024-11-15T10:30:00Z&limit=20
  • Відповідь: { items: [...], next_cursor: "...", has_more: true }

При OFFSET на 100-й сторінці база вичитує 2000 рядків тільки щоб пропустити. При великій кількості підписок та постів — секунди очікування.

Кеширование на клієнті

iOS — зберігайте перші 50-100 постів ленти у CoreData або Realm. При відкритті програми — миттєво покажіть кеш, одночасно запитайте нові пости. Коли нові пості прийшли — тихо вставте їх на початок (або покажіть баннер). NSFetchedResultsController + NSDiffableDataSourceSnapshot для гладкого оновлення без мерцання.

Android — Room + Paging 3 з RemoteMediator. Локальна база — джерело істини, RemoteMediator підгружає дані з мережі у Room, Paging 3 рендерить з Room.

Flutter — Hive або Isar для локального кешу, flutter_bloc для управління станом сторінок.

Алгоритмічна лента

Хронологічна лента — базис. Якщо потрібна алгоритмічна (ранжування за engagement): зберігайте score за кожний пост, перераховуйте через worker (BullMQ/Celery) при додаванні лайків/коментарів. Клієнт запитує ленту з параметром sort=ranked. Для першого запуску — хронологічна, після набору даних — переключення на алгоритмічну. Обидві ленти як окремі вкладки (Reels vs Following у Instagram).

Скролинг та продуктивність

UICollectionView з UICollectionViewCompositionalLayout та DiffableDataSource — золотий стандарт на iOS. Prefetch даних через UICollectionViewDataSourcePrefetching. Зображення — Kingfisher з кешуванням у пам'яті та на диску.

На Android LazyColumn (Compose) або RecyclerView з ConcatAdapter. Зображення — Coil з rememberAsyncImagePainter.

Головна причина дерганої прокрутки — декодування зображень на main thread. Kingfisher та Coil роблять це у background за замовчуванням. При кастомному завантаженні зображень — DispatchQueue.global(qos: .userInitiated).async (iOS) або Dispatchers.IO (Android).

Етапи роботи

Вибір архітектури ленти (fan-in/fan-out/гібрид) під очікувану навантаження → API з cursor-пагінацією → UI ленти з кешем → realtime-обновлення → нагрузкове тестування (k6) на сценарій «1000 запитів ленти одночасно».

Часові рамки

Базова лента з pull-to-refresh та пагінацією — 2-3 дні. З realtime WebSocket, кешем, алгоритмічним ранжуванням — 7-10 днів. Вартість розраховується індивідуально.