Пагинация в мобилното разработване — какво е, видове и принцип на работа

Автор: IT Sectr Публикувано: 2026-03-11 Време за четене: 9 мин

Пагинацията — техника за странично зареждане на данни, използвана в мобилни приложения и уеб услуги за работа с големи набори от записи. Според Android Developers Documentation (2025), правилното имплементиране на пагинация намалява натоварването на API, спестява трафик и подобрява потребителското изживяване. Постраничното зареждане позволява на приложението да показва съдържание постепенно, без да чака пълното зареждане на всички данни.

Основни моменти

  • Пагинация — начин за зареждане на големи набори от данни на порции за оптимизиране на производителността и трафика.
  • Offset пагинация използва отместване (page/offset) за навигация — прост, но нестабилен метод при чести вмъквания.
  • Cursor пагинация използва уникален курсор от последния запис — стабилна при промяна на данните между заявките.
  • Keyset пагинация филтрира по колона с уникален индекс — ефективна за големи таблици без дубликати.
  • Time-based пагинация групира записите по времеви маркери — удобна за новинарски емисии и социални мрежи.

Какво е пагинация?

Пагинацията (от англ. pagination — разделяне на страници) — техника за разделяне на голям набор от данни на последователни порции (страници). В мобилните приложения пагинацията се използва при зареждане на списъци с съобщения, новинарски емисии, каталози с продукти, история на поръчки и всякакви други колекции с потенциално неограничен брой записи.

Без пагинация приложението е принудено да зарежда всички данни наведнъж, което води до дълго чакане, голям разход на трафик и нестабилна работа на слаби устройства. API заявка с пагинация връща само една порция данни и мета-информация за зареждане на следващата — по този начин приложението контролира обема на получената информация.

Основните метрики на пагинацията: размер на страницата (page size) — брой записи на една страница (обикновено 10-50), и номер на страница или курсор — указател на текущата позиция в набора. Изборът на размер на страницата зависи от типа данни: за компактни елементи (имена) са достатъчни 20-30, за картички с изображения — 10-15.

Защо е необходима пагинация в мобилните приложения

Мобилните устройства имат ограничени ресурси: обем на RAM, скорост на процесора и лимити на трафик. Пагинацията решава три ключови задачи: намаляване на консумацията на памет (в паметта се съхраняват само видимите елементи), ускоряване на първото показване (първата порция се зарежда по-бързо от целия набор) и икономия на трафик (данните се зареждат само когато потребителят превърта списъка).

Основни видове пагинация

Съществуват четири основни вида пагинация, всеки от които решава специфични задачи. Изборът на метод зависи от изискванията за консистентност на данните, архитектура на API, тип на съхранение и допустимата сложност на имплементация от страна на клиента и сървъра.

ТипПринцип на работаСтабилностСкорост при големи обеми
OffsetLIMIT + OFFSET в SQLнискаспада с нарастване на OFFSET
CursorWHERE id > last_idвисокастабилна (O(log n))
KeysetWHERE key > last_keyвисокастабилна (O(log n))
Time-basedWHERE created_at < last_timeсреднастабилна с индекс

Кога да използваме кой тип

Offset пагинацията е подходяща за статични или рядко актуализирани набори от данни, когато е важна простата имплементация. Cursor и Keyset — за динамични данни с чести вмъквания. Time-based — за хронологични емисии, където записите са подредени по време на създаване. Стандартът GraphQL Relay използва cursor пагинация като единствен препоръчителен метод.

Offset пагинация: предимства и недостатъци

Offset пагинацията — най-простият вид постранично зареждане. Клиентът предава параметри page и limit (или offset и limit), сървърът прилага SQL OFFSET и LIMIT. Например page=2, limit=20 ще върне записи от 21 до 40. Този метод е интуитивно разбираем и лесно се имплементира на всеки технологичен стек.

python
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items")
async def get_items(
    page: int = Query(default=1, ge=1),
    limit: int = Query(default=20, le=100)
):
    offset = (page - 1) * limit
    items = await fetch_items(offset, limit)
    total = await count_items()
    return {
        "items": items,
        "total": total,
        "page": page,
        "pages": (total + limit - 1) // limit
    }

Проблем с несъответствието на данните

Основният недостатък на Offset пагинацията — проблемът с пропуснати и дублиращи се записи. Ако между две заявки се добавят нови записи в таблицата, OFFSET се измества: потребителят може да види един и същ запис два пъти или да пропусне нов. Това е критично за новинарски емисии и чатове, където консистентността е важна.

Друг проблем — спад на производителността при големи OFFSET. Базата данни трябва да сканира и прескочи първите offset записа преди да върне резултата. При offset=100000 дори с LIMIT 20, сървърът ще отдели забележимо време за сканиране. PostgreSQL и MySQL демонстрират линейно намаляване на скоростта с нарастване на OFFSET.

Кога Offset все още е добър избор

Offset пагинацията остава най-добрият избор за: административни панели (данните се променят рядко, необходима е навигация между страници), отчети и исторически логове (фиксиран отрязък от данни), каталози с филтриране (може да се премине на произволна страница). Offset е и най-лесният за имплементиране от страна на клиента — RecyclerView с Paging 3 го поддържа веднага.

Keyset и Time-based пагинация

Keyset пагинацията използва уникален ключ (обикновено първичен ключ) за филтриране на записи. Вместо OFFSET заявката използва WHERE id > last_seen_id. Това осигурява стабилна производителност независимо от броя записи и липса на дубликати при вмъквания, тъй като новите записи винаги имат по-голямо id.

sql
-- Offset-пагинация (проблемная)
SELECT * FROM posts
ORDER BY id
LIMIT 20 OFFSET 100;

-- Keyset-пагинация (стабильная)
SELECT * FROM posts
WHERE id > 100
ORDER BY id
LIMIT 20;

Time-based пагинация

Time-based пагинацията (или времеви курсор) използва времевия маркер created_at за навигация. Клиентът предава timestamp на последния зареден запис, сървърът връща записи, създадени преди или след този маркер. Методът е популярен в социалните мрежи и новинарските емисии, където редът на записите се определя от времето на публикуване.

Характеристика на Time-based пагинацията — възможни дубликати, ако два записа са създадени в една и съща милисекунда. За отстраняване на този проблем се комбинира time-based ключ с уникално id: WHERE (created_at, id) < (last_time, last_id). Такъв съставен курсор гарантира уникалността на всеки запис и точен ред.

Сравнение на Keyset и Time-based

Keyset пагинацията изисква колона с уникална и монотонно нарастваща стойност (автоинкрементиращо id, UUID v7). Time-based е подходяща за всяка таблица с created_at, но изисква допълнителна обработка на дубликати. Основната разлика: Keyset работи стабилно при всякакви операции на вмъкване, докато Time-based е чувствителна към идентични времеви маркери.

Как да изберем тип пагинация за проекта

Изборът на тип пагинация зависи от характера на данните и изискванията за потребителско изживяване. По-долу са дадени препоръки за типични сценарии в мобилното разработване. Универсално решение не съществува — всеки метод има област на приложение, в която е оптимален.

  • Чат / месинджър — Cursor пагинация (по id на съобщението). Новите съобщения се добавят отгоре, курсорът не се измества.
  • Новинарска емисия — Time-based пагинация (по created_at). Записите са подредени по време, хронологията е важна.
  • Каталог с продукти — Offset пагинация. Потребителят може да премине на конкретна страница, данните се променят рядко.
  • История на поръчки — Cursor пагинация. Стабилността е важна, тъй като нови поръчки се добавят между зарежданията.
  • Коментари — Keyset пагинация. Всеки коментар има уникално id, големи обеми без дубликати.

Имплементация на Android с Paging 3

Библиотеката Android Paging 3 поддържа всички типове пагинация чрез PagingSource. За Offset — PagingSource с ключ Int (page), за Cursor — с ключ String или Long (cursor). PagingSource автоматично управлява зареждането, кеширането и повторните опити при грешки.

kotlin
class PostPagingSource(
    private val api: PostApi
) : PagingSource<Long, Post>() {

    override suspend fun load(
        params: LoadParams<Long>
    ): LoadResult<Long, Post> {
        val cursor = params.key ?: Long.MAX_VALUE
        return try {
            val response = api.getPosts(cursor, params.loadSize)
            LoadResult.Page(
                data = response.items,
                prevKey = null,
                nextKey = response.items.lastOrNull()?.id
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }

    override fun getRefreshKey(state: PagingState<Long, Post>): Long? {
        return state.anchorPosition?.let {
            state.closestItemToPosition(it)?.id
        }
    }
}

Препоръки за размер на страницата

Размерът на страницата влияе на скоростта на зареждане и възприемането на производителност. За мобилни приложения оптималният диапазон е 10-25 елемента на страница. По-малко от 10 — твърде чести заявки към API и рязко превъртане. Повече от 25 — дълго зареждане на първата порция при бавни мрежи.

За изображения и видео размерът на страницата се намалява до 5-10, тъй като всеки елемент изисква допълнително време за зареждане на медия. За списъци с текстови елементи (коментари, логове) размерът може да се увеличи до 30-50 записа. Препоръчва се размерът на страницата да бъде конфигурируем чрез API, за да може клиентът да се адаптира към различни мрежови условия.

Често задавани въпроси

Какво е пагинация с прости думи?

Пагинацията — зареждане на данни на порции, а не всички наведнъж. Като в книга: четете една страница, после прелиствате на следващата. В приложението това означава, че при превъртане на списъка се зарежда следващата порция данни, а не целият списък наведнъж, което спестява трафик и памет.

По какво се различава Offset от Cursor пагинация?

Offset брои записи: „пропусни 20, върни следващите 10„. Ако между зарежданията се добави нов запис — номерацията се измества. Cursor използва уникален идентификатор на последния запис: „върни 10 записа след ID = 100„. Новите записи не влияят на позицията.

Какъв размер на страницата за пагинация е оптимален?

За мобилни приложения оптимално е 10-25 елемента. За списъци с изображения — 5-10, за текстови емисии — 20-30. Размерът зависи от средния размер на един елемент: колкото по-тежък е елементът, толкова по-малка трябва да бъде страницата за бързо показване.

Как да имплементираме пагинация в RecyclerView?

Използвайте библиотеката Paging 3 от Android Jetpack. Тя предоставя PagingSource за зареждане, PagingData за реактивен поток и PagingDataAdapter за автоматично зареждане при превъртане. Библиотеката поддържа Offset, Cursor и Keyset пагинация чрез персонализиран PagingSource.

Какво е безкрайно превъртане и по какво се различава от пагинация?

Безкрайното превъртане — UI модел, при който нова порция данни се зарежда автоматично при приближаване до края на списъка. Пагинацията — механизъм за зареждане на данни на порции, а безкрайното превъртане е един от начините за неговото показване. Алтернативата е бутонът „Зареди още„.

Резюме

  • Пагинация — техника за зареждане на данни на порции, необходима за мобилни приложения с всякакви списъци.
  • Offset пагинация е лесна за имплементиране, но страда от неконсистентност при вмъквания и спад на производителност при големи OFFSET.
  • Cursor пагинация използва уникален идентификатор за навигация — стабилна и ефективна при всякакви обеми.
  • Keyset пагинация филтрира по първичен ключ, осигурявайки максимална производителност чрез използване на индекси.
  • Time-based пагинация групира записи по времеви маркери — идеална за хронологични емисии и социални мрежи.
  • Избор на метод зависи от характера на данните: за динамични — Cursor/Keyset, за статични — Offset, за емисии — Time-based.
  • Paging 3 на Android и стандартните cursor решения на iOS/уеб предоставят готова инфраструктура за всеки тип пагинация.

Ще разработим мобилно приложение под ключ

IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.

Обсъдете проекта

Прочетете също