Реалізація пагінації даних у мобільному додатку

Коли мобільний застосунок підвантажує тисячі записів одним запитом, користувачі стикаються з зависаннями та білим екраном. Ми впроваджуємо пагінацію на рівні API, щоб навігація залишалася плавною навіть при активному зростанні даних. Наша команда реалізує проєкт під ключ — від вибору стратегії до інтеграції та подальшої підтримки.

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

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

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

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Реалізація пагінації даних у мобільному додатку
Середній
від 1 дня до 3 днів
Часті запитання

Запит списку з 10 000 товарів одним викликом — класична помилка, яку наші інженери бачать у кожному третьому проєкті. API повертає 40 МБ JSON, додаток зависає на парсингу, користувач бачить білий екран на 8 секунд і йде. Ми впроваджуємо пагінацію на рівні контракту між клієнтом і сервером: це забезпечує зниження навантаження API в 3–5 разів і дає плавну навігацію без затримок. Оцініть API вашого проєкту — зв'яжіться з нами для аудиту.

Реалізація пагінації даних: offset чи cursor?

Більшість розробників беруть offset-пагінацію за замовчуванням — ?page=2&limit=20. Це працює, поки дані статичні. Варто додати живу стрічку, де записи вставляються на початок, і користувач на сторінці 3 пропустить записи або побачить дублі: INSERT на початок зсуває всі offset'и. На таблицях з 500 000+ рядків offset сканує до 100 000 рядків через індексацію B-tree — запит виконується за 200–400 мс.

Cursor-пагінація вирішує проблему: сервер повертає next_cursor, клієнт передає його в наступному запиті. Курсор — це опакний токен (зазвичай base64 від id + timestamp), який фіксує позицію в наборі даних. PostgreSQL-бекенди реалізують це через WHERE id < :cursor ORDER BY id DESC LIMIT 20. Жодних дублів, жодних пропусків. Швидкість запитів залишається стабільною — 50–100 мс незалежно від розміру таблиці.

Порівняння стратегій пагінації
Критерій Offset-пагінація Cursor-пагінація
Простота реалізації Висока Середня (потрібен курсор на бекенді)
Дублі/пропуски при вставці Так Ні
Продуктивність на великих таблицях Погіршується (O(N)) Стабільна (O(1))
Підтримка зміщення до довільної сторінки Так (page=3) Складно (тільки послідовний скрол)
Кешування Легке (сторінки по page) Потрібно зберігати курсори

Чому cursor-пагінація ефективніша за offset?

Cursor-пагінація краще за offset у 3 рази за швидкістю на таблицях від 100 000 рядків — бенчмарки показують зниження часу відповіді з 300 до 90 мс. Крім того, вона гарантує консистентність даних при паралельних вставках. Для стрічок новин, повідомлень у чатах і каталогів з частими оновленнями це обов'язковий вибір.

Як налаштувати кешування за допомогою RemoteMediator?

На Android з Paging 3 курсорна пагінація реалізується через RemoteMediator + PagingSource:

class ItemPagingSource(
    private val api: ItemsApi,
    private val query: String
) : PagingSource<String, Item>() {
    override suspend fun load(params: LoadParams<String>): LoadResult<String, Item> {
        return try {
            val response = api.getItems(
                cursor = params.key,
                limit = params.loadSize,
                query = query
            )
            LoadResult.Page(
                data = response.items,
                prevKey = null,
                nextKey = response.nextCursor
            )
        } catch (e: HttpException) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState<String, Item>): String? {
        return state.anchorPosition?.let { anchor ->
            state.closestPageToPosition(anchor)?.nextKey
        }
    }
}

LazyColumn у Compose підключається через collectAsLazyPagingItems() — це готовий binding, який обробляє стани Loading, Error, NotLoading без зайвого коду.

На iOS аналог — compositional layout з UICollectionViewDiffableDataSource і NSDiffableDataSourceSnapshot. Prefetch реалізується через UICollectionViewDataSourcePrefetching: метод prefetchItemsAt викликається за N комірок до краю, що дозволяє запустити мережевий запит заздалегідь. Без prefetch при швидкості скролу більше 500 px/s видно порожні комірки — користувач чекає підвантаження 1–2 секунди.

Як впровадити cursor-пагінацію на Android: покрокова інструкція

  1. Визначте контракт API: сервер повертає next_cursor у JSON-відповіді.
  2. Створіть PagingSource<String, Item>, який передає курсор у loadParams.key.
  3. Підключіть RemoteMediator для offline-кеша: RemoteMediator отримує дані з мережі та зберігає в Room.
  4. У PagingSource реалізуйте getRefreshKey, щоб після оновлення відновити позицію.
  5. Налаштуйте LazyColumn з collectAsLazyPagingItems() і явний LoadStateFooter з кнопкою retry.

Порівняння стратегій кешування: RemoteMediator vs. простий кеш

Параметр RemoteMediator + Room Простий кеш (LruCache)
Offline-доступ Так Ні
Консистентність при оновленнях ETag/Last-Modified Немає механізму
Складність реалізації Середня Низька
Економія трафіку 60–80% 0%
Рекомендація Високонавантажені проєкти Прототипи, статичні дані

Нескінченний скрол та pull-to-refresh

Нескінченний скрол без стану помилки — типова проблема. Мережа пропала на 5-й сторінці, запит завис, користувач скролить вниз і нічого не відбувається. Потрібен явний LoadStateFooter з кнопкою retry.

У Paging 3:

adapter.addLoadStateListener { loadState ->
    binding.retryButton.isVisible = loadState.source.append is LoadState.Error
    binding.progressBar.isVisible = loadState.source.append is LoadState.Loading
}

Pull-to-refresh скидає пагінацію до першої сторінки через adapter.refresh() — Paging 3 інвалідує PagingSource і починає заново. На SwiftUI це refreshable модифікатор, який викликає invalidateQueries() у TCA або оновлює @StateObject в'юмоделі. Для впровадження SwiftUI пагінації з кешуванням даних offline використовуйте комбінацію з CoreData та URLSession.

Кеш та offline

Paging 3 + Room — стандартна зв'язка для offline-first. RemoteMediator записує дані в локальну БД, PagingSource читає з Room, а не з мережі. Користувач бачить дані навіть без інтернету, свіжі дані підвантажуються фоном.

Ключовий момент: стратегія інвалідації кеша. Якщо сервер оновив запис, локальна копія застаріє. Рішення — ETag або Last-Modified у заголовках відповіді: клієнт надсилає If-None-Match, сервер повертає 304 без тіла при відсутності змін. Room оновлює лише змінені записи через @Insert(onConflict = OnConflictStrategy.REPLACE). Це знижує обсяг завантажуваних даних на 60–80%.

Що входить у роботу (під ключ)

  • Аудит поточного API та специфікація контракту пагінації.
  • Реалізація cursor/offset-пагінації на клієнті (Android/iOS/крос-платформа).
  • Інтеграція RemoteMediator та Room для offline-режиму.
  • Налаштування prefetch та retry-логіки.
  • Тестування на реальних пристроях з імітацією поганої мережі.
  • Документація коду та рекомендації щодо доопрацювання бекенду.
  • Підтримка після впровадження: 2 тижні консультацій.

Терміни та вартість

Проста offset-пагінація без кеша — 1–2 дні. Cursor-пагінація з RemoteMediator, offline-кешем та retry-логікою — 3–5 днів. Терміни та обсяг роботи узгоджуються індивідуально після аналізу вимог та існуючого API. Ми маємо 5+ років досвіду в мобільній розробці та понад 30 проєктів з пагінацією — довіртеся нашим спеціалістам. Оцініть проєкт: пишіть нам для аудиту пагінації вашого додатка — ми підберемо оптимальне рішення.

Типові помилки при впровадженні пагінації

  • Відсутність prefetch на iOS — порожні комірки при швидкому скролі.
  • Використання offset у стрічці з частими вставками — дублі та пропуски.
  • Ігнорування станів завантаження та помилок: користувач не бачить індикатора.
  • Відсутність кешування — кожен скрол викликає мережевий запит.
  • Неправильний вибір розміру сторінки: 5 елементів — часті підвантаження, 100 — довге очікування.

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

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

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1010
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    903
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1332
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1180
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1107
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    714