Ang Pagination — isang pamamaraan ng pag-load ng data ng pahina-sa-pahina, na ginagamit sa mga mobile application at web service para sa pagtatrabaho sa malalaking set ng mga tala. Ayon sa Android Developers Documentation (2025), ang tamang implementasyon ng pagination ay nagbabawas ng karga sa API, nakatipid ng trapiko at nagpapabuti ng karanasan ng gumagamit. Pag-load ng pahina-sa-pahina ay nagpapahintulot sa app na magpakita ng nilalaman nang paunti-unti, nang hindi naghihintay ng kumpletong pag-load ng lahat ng data.
Mga Pangunahing Punto
Pagination (mula sa Ingles pagination — paghahati sa pahina) — isang pamamaraan ng paghahati ng malaking set ng data sa sunud-sunod na mga bahagi (pahina). Sa mga mobile app, ginagamit ang pagination sa pag-load ng mga listahan ng mensahe, news feed, katalogo ng produkto, kasaysayan ng order, at anumang iba pang koleksyon na may potensyal na walang limitasyong bilang ng mga tala.
Kung walang pagination, ang app ay mapipilitang i-load ang lahat ng data nang sabay-sabay, na nagreresulta sa mahabang paghihintay, mataas na konsumo ng trapiko, at hindi matatag na paggana sa mahihinang device. Ang kahilingan sa API na may pagination ay nagbabalik lamang ng isang bahagi ng data at meta-impormasyon para sa pag-load ng susunod — sa ganitong paraan, kinokontrol ng app ang dami ng natatanggap na impormasyon.
Ang mga pangunahing sukatan ng pagination: sukat ng pahina (page size) — bilang ng mga tala sa isang pahina (karaniwang 10-50), at numero ng pahina o cursor — tagapahiwatig ng kasalukuyang posisyon sa set. Ang pagpili ng sukat ng pahina ay depende sa uri ng data: para sa mga compact na elemento (pangalan) sapat na ang 20-30, para sa mga card na may larawan — 10-15.
Ang mga mobile device ay may limitadong mapagkukunan: dami ng RAM, bilis ng processor, at mga limitasyon sa trapiko. Ang pagination ay lumulutas ng tatlong pangunahing gawain: pagbawas ng konsumo ng memorya (tanging mga nakikitang elemento ang naka-imbak sa memorya), pagpapabilis ng unang pagpapakita (ang unang bahagi ay nag-load nang mas mabilis kaysa sa buong set) at pagtipid ng trapiko (ang data ay naglo-load lamang kapag nag-scroll ang gumagamit sa listahan).
May apat na pangunahing uri ng pagination, bawat isa ay lumulutas ng mga tiyak na gawain. Ang pagpili ng paraan ay depende sa mga kinakailangan para sa pagkakapare-pareho ng data, arkitektura ng API, uri ng imbakan, at pinapayagang pagiging kumplikado ng implementasyon sa kliyente at server.
| Uri | Prinsipyo ng Paggana | Katatagan | Bilis sa malalaking volume |
|---|---|---|---|
| Offset | LIMIT + OFFSET sa SQL | mababa | bumababa sa pagtaas ng OFFSET |
| Cursor | WHERE id > last_id | mataas | matatag (O(log n)) |
| Keyset | WHERE key > last_key | mataas | matatag (O(log n)) |
| Time-based | WHERE created_at < last_time | katamtaman | matatag sa index |
Ang Offset pagination ay angkop para sa static o bihirang na-update na mga set ng data, kapag mahalaga ang simpleng implementasyon. Cursor at Keyset — para sa dynamic na data na may madalas na pagpasok. Time-based — para sa kronolohikal na mga feed, kung saan ang mga tala ay nakaayos ayon sa oras ng paglikha. Ang GraphQL na pamantayan Relay ay gumagamit ng cursor pagination bilang tanging inirerekomendang paraan.
Offset pagination — ang pinakasimpleng uri ng pag-load ng pahina-sa-pahina. Ang kliyente ay nagpapadala ng mga parameter na page at limit (o offset at limit), ang server ay nag-aplay ng SQL OFFSET at LIMIT. Halimbawa, page=2, limit=20 ay magbabalik ng mga tala 21 hanggang 40. Ang paraang ito ay intuitive at madaling ma-implement sa anumang teknolohikal na stack.
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
}
Ang pangunahing kahinaan ng Offset pagination — problema ng mga hindi nasasagot at dobleng tala. Kung sa pagitan ng dalawang kahilingan ay may idinagdag na mga bagong tala sa talahanayan, ang OFFSET ay gumagalaw: maaaring makita ng gumagamit ang parehong tala nang dalawang beses o makaligtaan ang bago. Ito ay kritikal para sa mga news feed at chat kung saan mahalaga ang pagkakapare-pareho.
Ang isa pang problema — pagbaba ng pagganap sa malalaking OFFSET. Ang database ay kailangang i-scan at laktawan ang unang offset na mga tala bago ibalik ang resulta. Sa offset=100000 kahit na may LIMIT 20, ang server ay gugugol ng kapansin-pansing oras sa pag-scan. Ang PostgreSQL at MySQL ay nagpapakita ng linyar na pagbaba ng bilis sa pagtaas ng OFFSET.
Ang Offset pagination ay nananatiling pinakamahusay na pagpipilian para sa: mga panel ng administrasyon (bihirang magbago ang data, kailangan ang nabigasyon sa mga pahina), mga ulat at historikal na log (nakapirming hiwa ng data), mga katalogo na may pagsala (maaaring mag-navigate sa anumang pahina). Ang Offset ay pinakamadali ring ma-implement sa panig ng kliyente — ang RecyclerView na may Paging 3 ay sumusuporta dito kaagad.
Ang Keyset pagination ay gumagamit ng natatanging susi (karaniwang pangunahing susi) para sa pagsala ng mga tala. Sa halip na OFFSET, ang kahilingan ay gumagamit ng WHERE id > last_seen_id. Tinitiyak nito ang matatag na pagganap anuman ang bilang ng mga tala at kawalan ng mga duplicate sa pagpasok, dahil ang mga bagong tala ay laging may mas malaking id.
-- Offset pagination (problematiko)
SELECT * FROM posts
ORDER BY id
LIMIT 20 OFFSET 100;
-- Keyset pagination (stable)
SELECT * FROM posts
WHERE id > 100
ORDER BY id
LIMIT 20;
Ang Time-based pagination (o cursor ng oras) ay gumagamit ng timestamp na created_at para sa nabigasyon. Ang kliyente ay nagpapadala ng timestamp ng huling na-load na tala, ang server ay nagbabalik ng mga tala na nilikha bago o pagkatapos ng timestamp na ito. Ang paraan ay popular sa mga social network at news feed, kung saan ang pagkakasunud-sunod ng mga tala ay tinutukoy ng oras ng paglalathala.
Ang katangian ng Time-based pagination — posibleng mga duplicate kung dalawang tala ay nilikha sa parehong millisecond. Upang alisin ang problemang ito, pinagsasama ang time-based na susi na may natatanging id: WHERE (created_at, id) < (last_time, last_id). Ang ganitong tambalang cursor ay ginagarantiyahan ang pagiging natatangi ng bawat tala at eksaktong pagkakasunod-sunod.
Ang Keyset pagination ay nangangailangan ng column na may natatangi at monotonically na tumataas na halaga (auto-increment id, UUID v7). Ang Time-based ay angkop para sa anumang talahanayan na may created_at, ngunit nangangailangan ng karagdagang pagproseso ng mga duplicate. Ang pangunahing pagkakaiba: Ang Keyset ay gumagana nang matatag sa anumang operasyon ng pagpasok, habang ang Time-based ay sensitibo sa magkaparehong mga timestamp.
Ang pagpili ng uri ng pagination ay depende sa katangian ng data at mga kinakailangan para sa karanasan ng gumagamit. Nasa ibaba ang mga rekomendasyon para sa mga tipikal na senaryo sa mobile development. Walang unibersal na solusyon — bawat paraan ay may lugar ng aplikasyon kung saan ito ay optimal.
Ang library na Android Paging 3 ay sumusuporta sa lahat ng uri ng pagination sa pamamagitan ng PagingSource. Para sa Offset — PagingSource na may Int na susi (page), para sa Cursor — na may String o Long na susi (cursor). Awtomatikong pinamamahalaan ng PagingSource ang pag-load, caching, at muling pagsubok sa mga error.
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
}
}
}
Ang laki ng pahina ay nakakaapekto sa bilis ng pag-load at persepsyon ng pagganap. Para sa mga mobile app, ang optimal na saklaw ay 10-25 elemento bawat pahina. Mas mababa sa 10 — masyadong madalas na mga kahilingan sa API at maalog na pag-scroll. Higit sa 25 — matagal na pag-load ng unang bahagi sa mabagal na network.
Para sa mga larawan at video, ang laki ng pahina ay binabawasan sa 5-10, dahil ang bawat elemento ay nangangailangan ng karagdagang oras para sa pag-load ng media. Para sa mga listahan na may tekstuwal na elemento (komento, log), ang laki ay maaaring tumaas sa 30-50 tala. Inirerekomenda na ang laki ng pahina ay maaring i-configure sa pamamagitan ng API, upang ang kliyente ay makaangkop sa iba't ibang kondisyon ng network.
Mga Madalas Itanong
Ang pagination — pag-load ng data sa mga bahagi, hindi lahat nang sabay-sabay. Tulad sa isang libro: nagbabasa ka ng isang pahina, pagkatapos ay lumipat sa susunod. Sa app, nangangahulugan ito na sa pag-scroll ng listahan, ang susunod na bahagi ng data ay naglo-load, hindi ang buong listahan nang sabay-sabay, na nakakatipid ng trapiko at memorya.
Ang Offset ay nagbibilang ng mga tala: “laktawan ang 20, ibalik ang susunod na 10”. Kung sa pagitan ng mga pag-load ay may idinagdag na bagong tala — nagbabago ang bilangan. Ang Cursor ay gumagamit ng natatanging tagatukoy ng huling tala: “ibalik ang 10 tala pagkatapos ng ID = 100”. Ang mga bagong tala ay hindi nakakaapekto sa posisyon.
Para sa mga mobile app, optimal ang 10-25 elemento. Para sa mga listahan na may larawan — 5-10, para sa mga text feed — 20-30. Ang laki ay depende sa average na laki ng isang elemento: mas mabigat ang elemento, mas maliit dapat ang pahina para sa mabilis na pagpapakita.
Gamitin ang library na Paging 3 mula sa Android Jetpack. Nagbibigay ito ng PagingSource para sa pag-load, PagingData para sa reactive stream, at PagingDataAdapter para sa awtomatikong pag-load habang nag-scroll. Sinusuportahan ng library ang Offset, Cursor, at Keyset pagination sa pamamagitan ng custom na PagingSource.
Ang infinite scroll — pattern ng UI kung saan ang bagong bahagi ng data ay awtomatikong naglo-load kapag papalapit sa dulo ng listahan. Ang pagination — mekanismo ng pag-load ng data sa mga bahagi, at ang infinite scroll ay isa sa mga paraan ng pagpapakita nito. Ang alternatibo ay ang button na “Mag-load pa”.
Buod
Gagawa kami ng mobile application na turnkey
Gumagawa ang IT Sectr ng mga iOS at Android application para sa mga startup at negosyo mula noong 2017. Magpapayo kami sa iyo at magmumungkahi ng pinakamahusay na solusyon.
Basahin din