Offset Pagination i mobilutveckling: vad är det och hur implementerar man det

Författare: IT Sectr Publicerad: 2026-03-11 Lästid: 10 min

Offset Pagination — sidnumrering med offset — metod för sidvis laddning av data via HTTP API. Klienten skickar parametrarna offset (förskjutning från början) och limit (sidstorlek), och servern returnerar poster från offset-positionen. Enligt REST API Tutorial används detta tillvägagångssätt i stor utsträckning i RESTful-tjänster på grund av enkel implementering. Vid stora datamängder förlorar dock offset-sidnumrering prestanda på grund av fullständig genomsökning av tabellen till önskad position.

Huvudpunkter

  • Offset Pagination — sidnumreringsmetod där servern hoppar över N poster och returnerar nästa M.
  • Enkelhet i implementering gör det till standard för REST API och mobila klienter.
  • Hoppningsproblem — vid insättning av poster mellan förfrågningar ser användaren dubbletter.
  • Datasprång — borttagning av poster leder till sidförskjutning och innehållsförlust.
  • Cursor-based sidnumrering löser dessa problem genom en pekare till den sista posten istället för offset.

Vad är Offset Pagination?

Offset Pagination — är en metod för sidvis uppdelning av data, där klientförfrågan innehåller två parametrar: offset (hur många poster som ska hoppas över) och limit (hur många poster som ska returneras). Servern utför en SQL-fråga med OFFSET och LIMIT, hoppar över det angivna antalet rader och returnerar resultatuppsättningen med fast storlek.

Metoden uppstod i relationsdatabaser som det enklaste sättet att organisera navigering mellan sidor och överfördes till HTTP API i takt med utvecklingen av REST-arkitektur. Offset Pagination kräver inte lagring av tillstånd på servern — varje förfrågan är oberoende och innehåller all information som behövs för att hämta data.

Enligt forskning om API-design från Postman (2025) används offset-sidnumrering i 72% av offentliga REST API:er, vilket gör det till den dominerande standarden trots kända prestandabegränsningar vid stora datamängder.

Struktur för förfrågan och svar

En typisk REST-förfrågan med Offset Pagination innehåller frågeparametrarna offset och limit. Svaret innehåller en lista med poster från den begärda sidan och metadata för att bygga navigeringsgränssnittet.

Parametern limit begränsar antalet returnerade poster och skyddar servern och klienten från överdriven belastning. Typiska limit-värden — från 10 till 50 poster per sida beroende på datakomplexitet.

kotlin
data class PageRequest(
    val offset: Int,
    val limit: Int
)

data class PageResponse<T>(
    val items: List<T>,
    val total: Int,
    val hasMore: Boolean
)

fun RetrofitApi.fetchPage(request: PageRequest): Call<PageResponse<Item>>

Hur Offset Pagination fungerar

Offset Pagination omvandlas till en SQL-fråga med konstruktionerna OFFSET och FETCH NEXT (eller LIMIT i MySQL/SQLite). Databasservern skannar tabellen, hoppar över antalet rader som är lika med offset och returnerar nästa limit rader. Ju större offset, desto längre tid tar frågan.

Prestandaproblemet beror på att databasen inte direkt kan gå till offset-positionen — den måste läsa och kassera alla föregående rader. Vid offset = 100000 och limit = 20 läser DBMS 100020 rader och returnerar endast 20.

SQL-frågan under huven

SQL — språket som servern använder för att utföra offset-sidnumrering. I PostgreSQL och MySQL används LIMIT, i SQL Server och Oracle — OFFSET...FETCH. Olika DBMS optimerar denna fråga på sina egna sätt, men det grundläggande skanningsproblemet förblir detsamma.

sql
SELECT id, title, created_at
FROM articles
ORDER BY created_at DESC
OFFSET 100000 ROWS
FETCH NEXT 20 ROWS ONLY;

Konsistensproblem

Datakonsistens — den största nackdelen med Offset Pagination vid arbete med dynamiska uppsättningar. Om en ny post läggs till i början av tabellen mellan två användarförfrågningar, flyttas alla befintliga poster. Användaren ser dubbletter eller hopp.

Föreställ dig en tabell med 100 poster med limit = 20. På sida 1 ser användaren poster 1-20. Administratören lägger till 5 nya poster. På sida 2 ser användaren poster 26-45 istället för förväntade 21-40 — poster 21-25 hoppas över och poster 21-25 från föregående uppsättning dupliceras på sida 1.

Offset vs Cursor-based: jämförelse av metoder

Cursor-based pagination — ett alternativ till Offset Pagination, som använder en pekare till den sista posten på den aktuella sidan. Istället för numerisk förskjutning skickar klienten identifieraren för den senast mottagna posten, och servern returnerar nästa N poster efter den.

Cursor-based-metoden löser konsistensproblemet: markörens position ändras inte vid insättningar eller borttagningar, eftersom markören refererar till en specifik post, inte till en position. Den är dock mer komplex att implementera — kräver ett unikt sorterbart fält (vanligtvis ID eller timestamp).

ParameterOffset PaginationCursor-based Pagination
EnkelhetHög — två numeriska parametrarMedel — kodning av markör krävs
KonsistensLåg — dubbletter vid insättningHög — markör oberoende av ändringar
PrestandaMinskar med växande offsetStabil vid alla volymer
Hopp till sidaJa — kan gå till valfri sidaNej — endast sekventiell navigering
Lämplig förTabeller <10K poster, UI med sidnummerFlöden, oändlig scroll, stora uppsättningar

Valet mellan metoder beror på användarens gränssnittskrav. Om navigering med sidnummer och direkt hopp behövs — är Offset Pagination enklare. För oändlig scroll eller nyhetsflöden är markörer att föredra.

Keyset pagination

Keyset pagination — en variant av cursor-based-metoden, där filtrering sker med en unik nyckel med WHERE istället för OFFSET. SQL-frågan använder villkoret WHERE id > lastId, vilket gör att databasen kan använda index utan att skanna kasserade rader.

Enligt PostgreSQL Wiki körs keyset pagination 100-1000 gånger snabbare än en offset-fråga vid stora förskjutningar, eftersom indexskanning ersätter fullständig tabellgenomgång. Nackdel — omöjlighet att hoppa till en godtycklig sida utan sekventiell genomgång.

När ska Offset Pagination användas

Offset Pagination är optimal för små och medelstora datamängder (upp till 10000 poster), där användaren behöver ett gränssnitt med sidnummer. Typiska scenarier — adminpaneler, orderlistor, kataloger med filtrering och sidnumrering.

För mobila applikationer är offset-sidnumrering lämplig vid laddning av historisk data, där insättning av nya poster är sällsynt eller omöjlig — till exempel användarens orderhistorik, lista över slutförda uppgifter, transaktionsarkiv. I dessa scenarier uppstår inte konsistensproblemet.

Rekommenderas inte att använda Offset Pagination för sociala media-flöden, kommentarlistor, chattar och andra dynamiska uppsättningar med frekventa insättningar. I dessa fall försämrar hopp och dubbletter användarupplevelsen och kräver ytterligare dedupliceringslogik på klienten.

Hybridmetod

Hybridsidnumrering kombinerar offset och markör: den första förfrågan använder offset för att visa startsidan, och efterföljande använder markör för att ladda oändlig scroll. Denna metod är implementerad i Instagram och Twitter, där den första sidan laddas via markör, men offset används för att beräkna positionen vid återgång till föregående vy.

Implementering av hybridmetoden kräver lagring av användarens virtuella position på klienten och koordination av två sidnumreringsmekanismer på servern. Enligt Instagram Engineering-bloggen använder deras team cursor-based-sidnumrering med ett extra fält startCursor, som ersätter offset för initial laddning.

Offset Pagination i mobila applikationer

Mobila applikationer använder Offset Pagination tillsammans med Retrofit/OkHttp på Android och URLSession/Combine på iOS. Det typiska mönstret — laddning av nästa sida vid scrollning till slutet av listan via RecyclerView.OnScrollListener eller UICollectionView prefetching.

Implementering av offset-sidnumrering på en mobil klient omfattar tre komponenter: sidnumreringshanterare (lagrar aktuell offset och hasMore), listadapter (visar element och laddningsindikator) och repository (utför förfrågningar och hanterar fel). Android Jetpack erbjuder Paging 3-biblioteket, som stöder både offset- och cursor-based-sidnumrering direkt från lådan.

Implementering på Kotlin med Paging 3

Paging 3 — Android Jetpack-bibliotek för sidvis laddning av data. Det kapslar in sidnumreringslogik, inklusive offset-spårning, laddningsstatushantering och automatisk laddning vid scrollning. PagingSource definierar nycklar för nästa och föregående sida.

kotlin
class OffsetPagingSource(
    private val api: ApiService,
    private val limit: Int = 20
) : PagingSource<Int, Item>() {

    override suspend fun load(
        params: LoadParams<Int>
    ): LoadResult<Int, Item> {
        val offset = params.key ?: 0
        return try {
            val response = api.getItems(offset, limit)
            LoadResult.Page(
                data = response.items,
                prevKey = null,
                nextKey = if (response.hasMore) offset + limit else null
            )
        } catch (e: Exception) {
            LoadResult.Error(e)
        }
    }
}

PagingSource definierar nycklarna prevKey och nextKey för sidnavigering. Vid offset-sidnumrering är prevKey alltid null (kan inte gå till föregående sida utan att spara historik), och nextKey ökar med limit vid varje laddning, tills servern returnerar hasMore = false. Detta är en enkel och förutsägbar modell för mobila listor.

Vanliga misstag vid Offset Pagination

Första misstaget — att förlita sig på posternas ordning utan sortering. Offset Pagination kräver stabil ORDER BY-sortering på ett unikt fält. Utan detta kan DBMS returnera poster i godtycklig ordning, vilket leder till slumpmässiga dubbletter och hopp mellan sidor.

Andra misstaget — att använda offset för att beräkna sidnummer i gränssnittet. Formeln page = offset / limit + 1 fungerar endast under förutsättning att ingen post har tagits bort eller lagts till mellan laddningar. Vid dynamisk data blir sidnumret felaktigt och användaren ser felaktig information.

Tredje misstaget — att ignorera timeouts för frågor med stor offset. Vid offset över 100000 kan frågan ta tiotals sekunder, blockera gränssnittet och förbruka serverresurser. Det rekommenderas att ställa in ett maximalt offsetvärde på API-nivå (till exempel 10000) och använda cursor-based-sidnumrering för stora volymer.

Fjärde misstaget — att inte lägga till total count i svaret. Utan det totala antalet poster kan klienten inte visa antalet sidor och implementera sidnumrering med nummer. Att beräkna COUNT(*) på stora tabeller är dock också kostsamt — för uppsättningar över 100000 poster, använd uppskattningar eller begränsa det maximala totalvärdet.

Vanliga frågor

Vad är skillnaden mellan Offset Pagination och Cursor-based?

Offset använder numerisk förskjutning (offset) för att hoppa över poster, medan markören använder en pekare till den sista posten på föregående sida. Offset är enklare att implementera, men lider av dubbletter vid insättning och prestandaförlust vid stora förskjutningar. Markören är stabil vid alla dataförändringar.

När fungerar Offset Pagination dåligt?

Offset-sidnumrering är ineffektiv vid offset över 10000 poster på grund av fullständig tabellskanning. Den är också olämplig för dynamiska uppsättningar (flöden, chattar) där nya poster dyker upp mellan förfrågningar — användaren ser hopp och dubbletter vid navigering.

Vilken limit är optimal för Offset Pagination?

Optimal limit beror på poststorlek och nätverkshastighet — från 10 till 50 element per sida. För listor med stora bilder, använd limit = 10-15, för textdata — 20-50. Tillåt alltid klienten att specificera sin egen limit med en maximal begränsning på servern (vanligtvis 100).

Hur hanterar man dubbletter vid Offset Pagination?

För att hantera dubbletter, använd deduplicering på klienten baserat på unikt ID, tillämpa stabil sortering på ett unikt fält eller byt till cursor-based-sidnumrering. Android Paging 3 stöder nyckel för automatisk deduplicering av listelement.

Kan Offset Pagination användas med GraphQL?

Ja, GraphQL stöder offset-sidnumrering genom argumenten offset och limit i frågan, även om Relay-specifikationen rekommenderar cursor-based-metoden. Biblioteken Apollo GraphQL och Relay erbjuder inbyggt stöd för offset-sidnumrering med automatisk sidstatushantering.

Sammanfattning

  • Offset Pagination — sidnumreringsmetod med parametrarna offset och limit för att hoppa över och begränsa poster vid sidvis laddning av data från API.
  • Enkelhet i implementering och oberoende förfrågningar gör Offset Pagination till standardmetoden för 72% av REST API:er (Postman-data, 2025).
  • Prestanda minskar vid offset över 10000 på grund av tabellskanning till önskad position — databasen läser alla kasserade rader.
  • Konsistensproblem — insättning och borttagning av poster mellan frågor leder till dubbletter och hopp i sidresultaten.
  • Cursor-based sidnumrering löser Offset Paginations problem genom en pekare till den sista posten istället för numerisk förskjutning.
  • Hybridmetod kombinerar offset för första sidan med cursor-laddning för oändlig scroll i mobila applikationer.
  • Rekommendation — använd Offset Pagination för statiska uppsättningar upp till 10000 poster och byt till markörer för stora volymer och dynamisk data.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också