0Pricing
Android Academy · Ders

RemoteMediator ve Önbelleğe Alma

Ağ ve veritabanı sayfalamasını birleştirin.

RemoteMediator ve Önbelleğe Alma, CoddyKit'te ücretsiz bir Android Academy dersidir. Bu, 4 dersinin 4. 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.

Çevrimdışı Öncelikli Sayfalama

Basit bir ağ PagingSource çalışır; ancak bağlantı kesilirse liste boş kalır. Sağlam bir uygulama için veritabanının tek gerçeklik kaynağı olmasını ve ağın veritabanını arka planda doldurmasını istersiniz.

RemoteMediator tam olarak bunu sağlar: verileri yerel veritabanından sayfalı olarak yükler ve veritabanında veri kalmadığında ağdan daha fazlasını getirir.

Mimari

RemoteMediator ile veriler tek yönde akar:

  • Kullanıcı arayüzü bir Room PagingSource üzerinden sayfalama yapar
  • Room, sonuna yaklaştığında RemoteMediator ağdaki sonraki sayfayı getirir
  • Ağ sonucu Room'a yazılır
  • Room yeni satırları yayınlar ve kullanıcı arayüzü güncellenir

Kullanıcı, çevrimdışıyken bile önbelleğe alınmış verileri her zaman anında görür.

// Network ---> RemoteMediator ---> Room (source of truth) ---> UI
// UI never reads the network directly

Ücretsiz Room PagingSource

Room, bir PagingSource öğesini otomatik olarak oluşturabilir. Yalnızca PagingSource<Int, Entity> döndüren bir sorgu tanımlayın; Room bunu uygular.

Kullanıcı arayüzünün gerçekten sayfalama yaptığı kaynak budur.

import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Query

@Dao
interface ArticleDao {
    @Query("SELECT * FROM articles ORDER BY position ASC")
    fun pagingSource(): PagingSource<Int, ArticleEntity>
}

RemoteMediator Alt Sınıfını Oluşturma

RemoteMediator<Key, Value>, gerekli bir load() yöntemine ve isteğe bağlı bir initialize() yöntemine sahiptir.

load(), bir LoadType (REFRESH, PREPEND veya APPEND) ve mevcut PagingState değerini alır, ardından bir MediatorResult döndürür.

import androidx.paging.ExperimentalPagingApi
import androidx.paging.RemoteMediator

@OptIn(ExperimentalPagingApi::class)
class ArticleRemoteMediator(
    private val api: ArticleApi,
    private val db: AppDatabase
) : RemoteMediator<Int, ArticleEntity>() {
    // override suspend fun load(loadType, state): MediatorResult
}

LoadType İşleme

load() içinde, LoadType değerine göre hangi sayfanın getirileceğine karar verirsiniz:

  • REFRESH - ilk sayfayı (veya sabitleyici öğenin çevresini) yükler
  • PREPEND - genellikle yapılacak bir şey yoktur; endOfPaginationReached = true döndürülür
  • APPEND - elimizdeki son sayfanın ardından gelen sayfayı yükler
val page: Int = when (loadType) {
    LoadType.REFRESH -> 1
    LoadType.PREPEND ->
        return MediatorResult.Success(endOfPaginationReached = true)
    LoadType.APPEND -> {
        val lastKey = db.remoteKeyDao().last()?.nextKey
            ?: return MediatorResult.Success(endOfPaginationReached = true)
        lastKey
    }
}

Uzak Anahtarlar Tablosu

Bir PagingSource öğesinin aksine, bir RemoteMediator sonraki/önceki anahtarları doğrudan döndüremez; bu anahtarlar kalıcı olarak saklanmalıdır. Bunları verilerinizin yanında küçük bir uzak anahtarlar tablosunda saklayın.

Bu sayede uygulama yeniden başlatıldığında APPEND/PREPEND işlemlerine devam edebilirsiniz.

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "remote_keys")
data class RemoteKey(
    @PrimaryKey val articleId: Int,
    val prevKey: Int?,
    val nextKey: Int?
)

Ağ Sonuçlarını Room'a Yazma

Bir sayfayı getirdikten sonra öğeleri ve anahtarlarını bir işlem içinde Room'a yazın. REFRESH sırasında önbelleğin tutarlı kalması için önce eski tabloları temizleyin.

db.withTransaction {
    if (loadType == LoadType.REFRESH) {
        db.remoteKeyDao().clearAll()
        db.articleDao().clearAll()
    }
    val nextKey = if (response.items.isEmpty()) null else page + 1
    db.remoteKeyDao().insertAll(
        response.items.map { RemoteKey(it.id, prevKey = page - 1, nextKey = nextKey) }
    )
    db.articleDao().insertAll(response.items.map { it.toEntity() })
}

Mediatör Sonucu Döndürme

load() işlemini bir MediatorResult döndürerek tamamlayın:

  • Daha fazla sayfa olmadığında Success(endOfPaginationReached = true)
  • Daha fazla sayfa bulunabileceğinde Success(endOfPaginationReached = false)
  • Başarısızlık durumunda, LoadState.Error olarak sunulan Error(e)
return try {
    val response = api.getArticles(page = page, size = state.config.pageSize)
    db.withTransaction { /* write items + keys */ }
    MediatorResult.Success(
        endOfPaginationReached = response.items.isEmpty()
    )
} catch (e: IOException) {
    MediatorResult.Error(e)
} catch (e: HttpException) {
    MediatorResult.Error(e)
}

Pager'ı remoteMediator ile Bağlama

Pager öğesini hem remoteMediator hem de Room pagingSourceFactory ile oluşturun. Mediatör Room'u doldurur; kullanıcı arayüzü Room üzerinden sayfalama yapar.

Deneysel bir API kullandığı için @OptIn(ExperimentalPagingApi::class) ile kullanıma izin verin.

@OptIn(ExperimentalPagingApi::class)
fun articles(): Flow<PagingData<ArticleEntity>> = Pager(
    config = PagingConfig(pageSize = 20),
    remoteMediator = ArticleRemoteMediator(api, db),
    pagingSourceFactory = { db.articleDao().pagingSource() }
).flow

APPEND için Anahtar Arama

Bir APPEND yüklemesi için, son yüklenen öğenin nextKey değerine ihtiyacınız vardır. Anahtarlar tablonuzdaki doğru uzak anahtarı bulmak için PagingState sabitleyicisini kullanın.

Yardımcı işlevler, REFRESH, APPEND ve PREPEND boyunca load() kodunun okunabilir kalmasını sağlar.

private suspend fun lastRemoteKey(
    state: PagingState<Int, ArticleEntity>
): RemoteKey? {
    return state.pages.lastOrNull { it.data.isNotEmpty() }
        ?.data?.lastOrNull()
        ?.let { db.remoteKeyDao().keyFor(it.id) }
}

// In load(): for APPEND
val nextKey = lastRemoteKey(state)?.nextKey
    ?: return MediatorResult.Success(endOfPaginationReached = true)

Önbelleğe Alma ve Güncellik

Veriler Room'da tutulduğu için uygulama anında yüklenir ve çevrimdışı çalışır. Güncelliğini yitirmiş içerikten kaçınmak için initialize() yöntemini geçersiz kılarak önbelleğin ne kadar eski olduğuna göre açılışta yenileme yapılıp yapılmayacağına karar verin.

override suspend fun initialize(): InitializeAction {
    val lastUpdate = db.remoteKeyDao().lastUpdatedMillis() ?: 0L
    val cacheTimeout = TimeUnit.HOURS.toMillis(1)
    return if (System.currentTimeMillis() - lastUpdate >= cacheTimeout) {
        InitializeAction.LAUNCH_INITIAL_REFRESH
    } else {
        InitializeAction.SKIP_INITIAL_REFRESH
    }
}

Hızlı Kontrol

Bir RemoteMediator kurulumunda, kullanıcı arayüzünün sayfalama yaptığı tek gerçeklik kaynağı nedir?

Özet: RemoteMediator ve Önbelleğe Alma

Çevrimdışı öncelikli bir sayfalama işlem hattı oluşturdunuz:

  • Kullanıcı arayüzü, tek gerçeklik kaynağı olan bir Room PagingSource üzerinden sayfalama yapar
  • RemoteMediator.load(), REFRESH/PREPEND/APPEND işlemlerini yönetir ve sonuçları bir işlem içinde Room'a yazar
  • Bir uzak anahtarlar tablosu, yeniden başlatmalar arasında sonraki/önceki anahtarları kalıcı olarak saklar
  • Pager hem bir remoteMediator hem de bir pagingSourceFactory alır
  • initialize(), önbelleğin güncelliğini denetler

Artık çevrimiçi veya çevrimdışı, sınırsız listeleri verimli biçimde yükleyebilirsiniz. Paging 3 kursunu tamamladığınız için tebrikler.

Sıkça Sorulan Sorular

“RemoteMediator ve Önbelleğe Alma” dersi ücretsiz mi?

Evet — “RemoteMediator ve Önbelleğe Alma” 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.

“RemoteMediator ve Önbelleğe Alma” dersinde ne öğreneceğim?

Ağ ve veritabanı sayfalamasını birleştirin. 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 4. dersidir.

“RemoteMediator ve Önbelleğe Alma” 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

  1. Sayfalama Neden Kullanılır
  2. PagingSource ve Pager
  3. Compose Listelerinde Sayfalama
  4. RemoteMediator ve Önbelleğe Alma
← Android Academy Sayfasına Dön