Repository Pattern: mi ez, adatabsztrakciós minta iOS-ben és Androidban

Szerző: IT Sectr Megjelenés: 2026-02-17 Olvasási idő: 7 perc

Repository Pattern — egy minta, amely absztrakciós réteget ad az üzleti logika és az adatforrások közé. A közvetlen API-, adatbázis- vagy gyorsítótár-hívások helyett a Repository egységes felületet biztosít az adatok lekéréséhez és mentéséhez. Ez leegyszerűsíti a tesztelést és a források közötti váltást. Bővebben a Android Data Layer dokumentációban.

Lényeg

  • Repository Pattern — köztes réteg az üzleti logika és az adatforrások (API, DB, gyorsítótár) között
  • DataSource — külön osztályok minden forráshoz: RemoteDataSource, LocalDataSource
  • Single source of truth — a Repository válik az UI réteg egységes adatforrásává
  • Tesztelés — a Repository könnyen helyettesíthető mock objektummal DI-n keresztül egységtesztekhez
  • Kompatibilitás — működik MVVM, Clean Architecture és más architekturális mintákkal

Mi a Repository Pattern a mobilfejlesztésben?

Repository Pattern — egy strukturális minta, amely elkülöníti az üzleti logikát az adatforrásokhoz való közvetlen hozzáféréstől. Ahelyett, hogy az Activity, UIViewController vagy ViewModel közvetlenül hívná a Retrofit-ot, URLSession-t, Room-ot vagy CoreData-t, a Repository-hoz fordulnak. A Repository dönti el, honnan vegye az adatokat: a hálózatból, adatbázisból vagy gyorsítótárból, és egységes formátumban adja vissza az eredményt. Ez az egyszeri felelősség elvének megvalósítása — az UI nem tudja, hogyan és honnan szerezték be az adatokat.

A Repository összetevői tartalmazzák az interfészt (protocol), a megvalósítást és egy vagy több DataSource-t. DataSource — egy osztály, amely egy forrással dolgozik: a RemoteDataSource API-t hív HTTP-kliensen keresztül, a LocalDataSource adatbázisba olvas és ír. A Repository a DataSource-okat a konstruktoron keresztül kapja (Dependency Injection), és eldönti, melyik forráshoz forduljon. Például egy felhasználói lista kérésénél a Repository először a gyorsítótárat, majd az adatbázist, végül a hálózatot ellenőrzi.

Előnyei a Repository Pattern-nek: az adatforrások változásainak elkülönítése (API-váltás, DB migráció) nem érinti az UI réteget; egységtesztelés a Repository vagy DataSource helyettesítésével; gyorsítótárazás átlátható az UI számára; váltás online és offline mód között a képernyő logikájának megváltoztatása nélkül. Az Android közösség a Repository-t kötelező rétegként ajánlja a Clean Architecture-ben.

Repository Pattern iOS-ben Swift segítségével: implementáció és példa

iOS implementáció a Repository Swift protokollokra épül. A Repository protokoll deklarálja az adatok lekérésére és mentésére szolgáló metódusokat. A tényleges megvalósítás az inicializálón keresztül kerül befecskendezésre — ez lehetővé teszi a megvalósítás cseréjét tesztekben és SwiftUI előnézetekben. A DataSource-ok is protokollokkal vannak deklarálva: Protocol RemoteDataSource, Protocol LocalDataSource. A ViewModel vagy Interactor nem ismeri a konkrét megvalósítást — csak a Repository protokollt ismeri.

swift
protocol UserRepository {
    func getUsers() async throws -> [User]
}

protocol UserRemoteDataSource {
    func fetchUsers() async throws -> [User]
}

protocol UserLocalDataSource {
    func getCachedUsers() throws -> [User]
    func saveUsers(_: [User]) throws
}

final class UserRepositoryImpl: UserRepository {
    private let remote: UserRemoteDataSource
    private let local: UserLocalDataSource

    init(remote: UserRemoteDataSource, local: UserLocalDataSource) {
        self.remote = remote
        self.local = local
    }

    func getUsers() async throws -> [User] {
        if let cached = try? local.getCachedUsers() {
            return cached
        }
        let users = try await remote.fetchUsers()
        try local.saveUsers(users)
        return users
    }
}

Dependency Injection iOS-ben a Repository számára általában gyáron vagy DI konténeren (Swinject, Factory) keresztül van konfigurálva. A tesztekben a UserRepository protokoll egy előre meghatározott adatokat visszaadó mock megvalósításra cserélődik. Az async-await szinkronná és olvashatóvá teszi a kódot lezárások és delegate-ek nélkül. A Combine reaktivitáshoz a Repository metódusai AnyPublisher-t adnak vissza az async throws helyett.

Repository Pattern Androidban Kotlin segítségével: példa Flow-val

Android implementáció a Repository széles körben használja a Kotlin Coroutines és Flow-t aszinkron műveletekhez. A Google a Repository-t ajánlja a hivatalos Android architektúra útmutatóban (Android Architecture Components). A Repository a konstruktoron keresztül kapja a RemoteDataSource-t (Retrofit) és LocalDataSource-t (Room), a ViewModel pedig feliratkozik a Repository Flow-jára. A Repository kezeli az adatstratégiát: először gyorsítótár, majd hálózat, vagy mindig hálózat a gyorsítótárba írással.

kotlin
interface UserRepository {
    fun getUsers(): Flow<Result<List<User>>>
}

interface UserRemoteDataSource {
    suspend fun fetchUsers(): List<User>
}

interface UserLocalDataSource {
    fun getCachedUsers(): Flow<List<User>>
    suspend fun saveUsers(users: List<User>)
}

class UserRepositoryImpl(
    private val remote: UserRemoteDataSource,
    private val local: UserLocalDataSource
) : UserRepository {

    override fun getUsers(): Flow<Result<List<User>>> = flow {
        emit(Result.Loading)
        local.getCachedUsers().collect { cached ->
            if (cached.isNotEmpty()) {
                emit(Result.Success(cached))
            }
        }
        try {
            val users = remote.fetchUsers()
            local.saveUsers(users)
            emit(Result.Success(users))
        } catch (e: Exception) {
            emit(Result.Error(e))
        }
    }
}

Result burkoló a fenti példában Android esetén szabványos: a sealed class Result tájékoztatja a ViewModel-t a betöltési állapotról (Loading, Success, Error). A ViewModel a collect-en keresztül fizet fel, és frissíti a StateFlow-t vagy LiveData-t. A Repository Flow-val automatikusan értesíti az UI-t az adatbázis változásairól — ez a kulcsfontosságú különbség az egyszeri lekérdezésekhez képest, ahol az UI manuális frissítés nélkül nem tud a változásokról.

DataSource: Remote, Local és adatgyorsítótárazás

DataSource — osztályok, amelyek egy adott adatforrással való munkáért felelősek. A RemoteDataSource HTTP-klienst (URLSession, Retrofit, Ktor) használ az adatok API-ból történő lekéréséhez. A LocalDataSource helyi tárolóval (CoreData, Realm, Room, UserDefaults, DataStore) dolgozik. Minden DataSource szűk felelősséggel rendelkezik: a RemoteDataSource csak az API-kérés formátumát ismeri, a LocalDataSource — az adatbázis sémáját. A Repository kombinálja őket, megvalósítva a gyorsítótárazási stratégiát.

DataSourceiOS platformAndroid platformForrás
RemoteURLSession + CodableRetrofit + Moshi/GsonREST / GraphQL API
Local (DB)CoreData, SwiftDataRoom, SQLDelightSQLite az eszközön
Local (gyorsítótár)NSCache, UserDefaultsDataStore, EncryptedSPMemóriában / lemezen
PreferenciaUserDefaults, KeychainSharedPreferences, EncryptedSPBeállítások, tokenek

Gyorsítótárazási stratégiák a Repository-ban: Cache-First (először gyorsítótár, majd háttérbetöltés), Network-Only (csak hálózat, fizetési képernyőkhöz), Network-First-With-Cache-Backup (először hálózat, hiba esetén — gyorsítótár). A stratégia kiválasztása a forgatókönyvtől függ: az országok listája hosszú ideig gyorsítótárazható, a devizaárfolyamok — 15 percig, a pénztárca egyenlege — csak a hálózatból. A Repository megvalósítja a stratégiát, és anélkül változtatja, hogy módosítaná a ViewModel-t vagy UI-t.

Repository Pattern vs Service Layer: különbségek és választás

Repository és Service — különböző minták átfedő funkciókkal. A Repository felelős az adatokhoz való hozzáférésért és azok gyorsítótárazásáért, adatmodelleket visszaadva. A Service (vagy Interactor, Use Case) üzleti logikát tartalmaz: validációt, adatátalakítást, több Repository hívásának orkesztrálását. A Service kombinálhatja a UserRepository-t, OrderRepository-t és NotificationRepository-t egy rendelés feldolgozásához. A Repository nem tartalmaz üzleti logikát — csak CRUD-ot és gyorsítótárazást.

Mikor válassza a Repository-t — adatnavigáció több forrással (API + DB + gyorsítótár), offline-first architektúra, gyorsítótárazás és átlátható forrásváltás szükségessége. A Repository kötelező a Clean Architecture-ben, és a Google ajánlja Android alkalmazásokhoz. Az iOS VIPER architektúrában a Repository szerepét az Interactor réteg tölti be, amely Manager vagy Service segítségével fér hozzá az adatokhoz.

Mikor elég a Service — egyszerű alkalmazások egy adatforrással, csak olvasható képernyők írás nélkül, offline mód nélküli projektek. Ilyen esetekben a DataSource-t közvetlenül a ViewModel vagy Presenter használja, a Repository pedig felesleges réteggé válik. A Repository korai szakaszban történő hozzáadása azonban nem igényel nagy költséget, és megkönnyíti a gyorsítótárazás és tesztek jövőbeli hozzáadását.

Gyakran Ismételt Kérdések

Miben különbözik a Repository a DataSource-tól?

DataSource — egy osztály, amely egy forrással dolgozik (API, DB, gyorsítótár). Repository — egy osztály, amely több DataSource-t kezel és egységes felületet biztosít. A Repository dönti el, melyik DataSource-ból vegye az adatokat, és koordinálja a gyorsítótárazást. A DataSource nem tud más források létezéséről, a Repository nem ismeri az egyes források megvalósításának részleteit.

Szükséges a Repository iOS-ben SwiftUI-val?

Igen, a Repository hasznos a SwiftUI-ban az adatok View-tól való elkülönítéséhez. A ViewModel feliratkozik a Repository Publisherére, a Repository pedig kezeli a gyorsítótárazást és szinkronizációt. Egyszerű alkalmazásokban a URLSession közvetlenül a ViewModel-ben is használható, de a tesztelhetőség és skálázhatóság érdekében a Repository előnyösebb. Az Apple nem kényszeríti ezt a mintát, de kompatibilis a SwiftData-val és Network.framework-kel.

Hogyan teszteljük a Repository-t több DataSource-szal?

A DataSource-ok Dependency Injection segítségével mock objektumokra cserélődnek. A teszt létrehoz egy mock RemoteDataSource-t (előre meghatározott JSON-t ad vissza) és egy mock LocalDataSource-t (ellenőrzi, hogy az adatok mentésre kerültek). A Repository elkülönítve kerül tesztelésre: ellenőrzik a gyorsítótárazási stratégiát, hibakezelést és a hívások helyes sorrendjét. Integrációs tesztekhez TestDispatcher (Kotlin) vagy MainActor.run (Swift) használatos.

Használható a Repository interfész (protocol) nélkül?

Lehet, de nem ajánlott. Protokoll nélkül nem cserélhető a megvalósítás tesztekben és előnézetben. Kotlinban a Repository interfész lehetővé teszi a megvalósítás cseréjét DI-n keresztül (Dagger, Hilt, Koin). Swiftben a Repository protokoll kötelező az async-await és Combine kód teszteléséhez. Kivétel — egyszerű projektek egy adatforrással, ahol a Repository nem tartalmaz gyorsítótárazási logikát.

Mi az offline-first a Repository kontextusában?

Offline-first — egy stratégia, amelyben az alkalmazás internet nélkül működik, helyi adatokat használva. A Repository kulcsszerepet játszik: először visszaadja az adatokat a helyi DataSource-ból, majd a háttérben szinkronizál a szerverrel. A felhasználó azonnal látja az adatokat, a Repository pedig frissíti azokat a hálózatról való betöltés után. A Room Flow-val biztosítja az UI reaktív frissítését a helyi adatbázis adatváltozásainál.

Összegzés

  • Repository Pattern — absztrakciós réteg az UI és adatforrások között
  • DataSource — külön osztályok API, DB és gyorsítótár számára
  • Protokollok — kötelezőek a teszteléshez és a megvalósítás cseréjéhez
  • Gyorsítótárazási stratégiák — Cache-First, Network-Only, Network-First-With-Cache-Backup
  • iOS — async-await vagy Combine protokollokkal
  • Android — Kotlin Flow + Room + Retrofit, a Google által ajánlott megközelítés
  • Tesztelés — mock DataSource DI-n keresztül, gyorsítótárazási stratégiák ellenőrzése

Kulcsrakész mobilalkalmazást fejlesztünk

Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.

Projekt megbeszélése

Olvassa el is