PagingSource ve Pager
Sayfaların nasıl yükleneceğini tanımlayın.
PagingSource ve Pager, CoddyKit'te ücretsiz bir Android Academy dersidir. Bu, 4 dersinin 2. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Android Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Android Academy kursu toplamda 4 dersten oluşur.
Sayfaların Nasıl Yükleneceğini Tanımlama
Bir ağ API'sinden sayfalı veri almak için bir PagingSource yazarsınız. Bu, Paging 3 için iki soruyu yanıtlar:
- Belirli bir anahtar için sayfayı nasıl yüklerim?
- Kullanıcı yenilerse nereden devam etmeliyim?
Daha sonra bunu, bir Flow<PagingData>'ya dönüştüren bir Pager içine sararsınız.
PagingSource Tür Parametreleri
PagingSource<Key, Value> iki tür parametresi alır:
- Key - bir sayfayı tanımlar. Sayfa numarası kullanan bir API için
Int, imleç kullanan bir API içinStringbelirtecidir. - Value - öğe türüdür; örneğin
Article.
import androidx.paging.PagingSource
import androidx.paging.PagingState
class ArticlePagingSource(
private val api: ArticleApi
) : PagingSource<Int, Article>() {
// implement load() and getRefreshKey()
}load() Uygulaması
load() bir suspend işlevidir. params.key (getirilecek sayfayı) alır ve bir LoadResult döndürür.
Başarılı olduğunda, öğelerle birlikte önceki ve sonraki anahtarları içeren LoadResult.Page döndürürsünüz. Bir anahtarın null olması, o yönde başka sayfa bulunmadığı anlamına gelir.
override suspend fun load(
params: LoadParams<Int>
): LoadResult<Int, Article> {
val page = params.key ?: 1 // first load has a null key
return try {
val response = api.getArticles(page = page, size = params.loadSize)
LoadResult.Page(
data = response.items,
prevKey = if (page == 1) null else page - 1,
nextKey = if (response.items.isEmpty()) null else page + 1
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}prevKey ve nextKey Neden Önemlidir
Paging, kullanıcı aşağı kaydırdıkça ileriye doğru yükleme yapmak için nextKey'i, geriye doğru yükleme yapmak içinse prevKey'i kullanır (listenin ortasından başlarken yararlıdır).
nextKey için null döndürmek, Paging'e başka sayfa olmadığını bildirir ve istek göndermeyi durdurur. Bunu unutmak, sonsuz sayıda boş isteğe neden olabilir.
// Stop forward paging when the server returns an empty page
nextKey = if (response.items.isEmpty()) null else page + 1
// Stop backward paging at the first page
prevKey = if (page == 1) null else page - 1getRefreshKey() Uygulaması
Liste yenilendiğinde (yenilemek için çekme veya geçersiz kılma), kullanıcının yaklaşık olarak aynı konumda kalması için Paging'in hangi sayfanın yeniden yükleneceğini bilmesi gerekir.
getRefreshKey(), geçerli anchorPosition değerini (görüntü alanına en yakın öğeyi) kullanarak uygun bir anahtar seçer.
override fun getRefreshKey(state: PagingState<Int, Article>): Int? {
return state.anchorPosition?.let { anchor ->
val closestPage = state.closestPageToPosition(anchor)
closestPage?.prevKey?.plus(1)
?: closestPage?.nextKey?.minus(1)
}
}Hataları Düzgün Yönetme
Ağ çağrısını bir try/catch bloğuna alın ve hata durumunda LoadResult.Error(e) döndürün. Paging bunu kullanıcı arayüzünde bir LoadState.Error olarak sunar; böylece yeniden deneme düğmesi gösterebilirsiniz.
Bir istisnanın load() dışına çıkmasına hiçbir zaman izin vermeyin; istisnayı yakalayıp LoadResult.Error değerine dönüştürün.
return try {
val response = api.getArticles(page = page, size = params.loadSize)
LoadResult.Page(
data = response.items,
prevKey = if (page == 1) null else page - 1,
nextKey = if (response.items.isEmpty()) null else page + 1
)
} catch (e: IOException) { // no network
LoadResult.Error(e)
} catch (e: HttpException) { // non-2xx response
LoadResult.Error(e)
}Pager Oluşturma
Bir Pager, PagingConfig ayarlarınızı yeni bir PagingSource oluşturan bir fabrikaya bağlar. .flow özelliği, kullanıcı arayüzünün topladığı bir Flow<PagingData>'dır.
Fabrika lambda'sı her seferinde yeni bir kaynak oluşturmalıdır; çünkü Paging, yenileme sırasında kaynağı geçersiz kılar ve yeniden oluşturur.
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import kotlinx.coroutines.flow.Flow
class ArticleRepository(private val api: ArticleApi) {
fun articleStream(): Flow<PagingData<Article>> = Pager(
config = PagingConfig(pageSize = 20, prefetchDistance = 5),
pagingSourceFactory = { ArticlePagingSource(api) }
).flow
}ViewModels için cachedIn
PagingData toplama işlemi tek seferliktir; yeniden toplamak yüklemeyi baştan başlatır. Yapılandırma değişikliklerinden etkilenmemek ve birden fazla toplayıcının verileri paylaşmasını sağlamak için akışı viewModelScope içinde cachedIn ile önbelleğe alın.
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.cachedIn
class ArticleViewModel(
repo: ArticleRepository
) : ViewModel() {
val articles = repo.articleStream()
.cachedIn(viewModelScope)
}loadSize ve pageSize Karşılaştırması
load() işlevinin, doğrudan yapılandırdığınız pageSize değerini değil params.loadSize değerini okuduğuna dikkat edin.
İlk yüklemede Paging daha büyük bir başlangıç bölümü isteyebilir (PagingConfig içindeki initialLoadSize tarafından denetlenir ve varsayılan olarak sayfa boyutunun 3 katıdır). İsteğin Paging'in beklediği değerle eşleşmesi için API'nize her zaman params.loadSize değerini gönderin.
// Correct: respect the size Paging asks for
val response = api.getArticles(page = page, size = params.loadSize)
// PagingConfig can tune the first load:
PagingConfig(pageSize = 20, initialLoadSize = 40)İmleç Tabanlı API'ler
Her API sayfa numaralarını kullanmaz. Bazıları sonraki sayfayı gösteren bir imleç veya belirteç döndürür. Kalıp aynıdır; yalnızca Key türünü String olarak değiştirin ve yanıttaki belirteci kullanın.
class CursorArticleSource(
private val api: ArticleApi
) : PagingSource<String, Article>() {
override suspend fun load(
params: LoadParams<String>
): LoadResult<String, Article> {
val cursor = params.key // null on first load
return try {
val res = api.getArticles(cursor = cursor, size = params.loadSize)
LoadResult.Page(
data = res.items,
prevKey = null, // forward-only cursor
nextKey = res.nextCursor // null when exhausted
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
override fun getRefreshKey(state: PagingState<String, Article>) = null
}Hepsini Birleştirme
Artık eksiksiz veri katmanına sahipsiniz: tek bir sayfayı yükleyen bir PagingSource, sayfaları akıtan bir Pager ve akışı önbelleğe alan bir ViewModel.
Kullanıcı arayüzü katmanı yalnızca viewModel.articles değerini toplar; bunu bir sonraki derste Compose LazyColumn ile görüntüleyeceğiz.
// Data layer summary
// 1. ArticlePagingSource : PagingSource<Int, Article>
// 2. Pager(config, factory).flow -> Flow<PagingData<Article>>
// 3. ViewModel: repo.articleStream().cachedIn(viewModelScope)
// UI just collects viewModel.articlesKısa Kontrol
Sayfa numarası kullanan bir PagingSource içinde load() işlevinden nextKey = null döndürülmesi neyi bildirir?
Özet: PagingSource ve Pager
Sayfalama için veri katmanını oluşturdunuz:
PagingSource<Key, Value>,load()vegetRefreshKey()işlevlerini uygularload(),prevKey/nextKeyiçerenLoadResult.PageveyaLoadResult.Errordöndürürnullanahtar, ilgili yöndeki sayfalamayı durdururPager(config, factory).flow, birFlow<PagingData>üretircachedIn(viewModelScope), yapılandırma değişiklikleri boyunca verileri korur
Sırada: bu akışı bir Compose listesinde görüntülemek var.
Yapay zeka eğitmeniyle Kotlin öğren — ücretsiz
Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.
- Kurslar
- 36
- Dersler
- 152
Sıkça Sorulan Sorular
“PagingSource ve Pager” dersi ücretsiz mi?
Evet — “PagingSource ve Pager” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Android Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Android Academy kursu toplamda 4 dersten oluşur.
“PagingSource ve Pager” dersinde ne öğreneceğim?
Sayfaların nasıl yükleneceğini tanımlayın. Android Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.
Android Academy öğrenmeye başlamak için deneyim gerekli mi?
Önceden deneyim gerekmez. CoddyKit'te Android Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 2. dersidir.
“PagingSource ve Pager” dersi ne kadar sürer?
Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.
Bu Android Academy dersinde kod yazıp çalıştırabilir miyim?
Evet. Her Android Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.
Bu kursun tüm dersleri
- Sayfalama Neden Kullanılır
- PagingSource ve Pager
- Compose Listelerinde Sayfalama
- RemoteMediator ve Önbelleğe Alma