Repository模式:iOS和Android中的数据抽象模式详解

作者: IT Sectr 发布日期: 2026-02-17 阅读时间: 7 分钟

Repository模式 — 一种在业务逻辑和数据源之间添加抽象层的模式。Repository提供统一的接口来获取和保存数据,而不是直接调用API、数据库或缓存。这简化了测试和源之间的切换。更多详情请参见Android Data Layer文档

要点

  • Repository模式 — 业务逻辑与数据源(API、数据库、缓存)之间的中间层
  • DataSource — 每个源的独立类:RemoteDataSource、LocalDataSource
  • 单一真实来源 — Repository成为UI层的统一数据源
  • 测试 — Repository可通过DI轻松替换为mock对象进行单元测试
  • 兼容性 — 与MVVM、Clean Architecture及其他架构模式兼容

移动开发中的Repository模式是什么?

Repository模式 — 一种将业务逻辑与数据源直接访问隔离开的结构性模式。Activity、UIViewController或ViewModel不再直接调用Retrofit、URLSession、Room或CoreData,而是向Repository请求数据。Repository决定从哪里获取数据:网络、数据库还是缓存,并以统一格式返回结果。这是单一职责原则的实现——UI不知道数据是如何以及从哪里获取的。

Repository的组件包括接口(protocol)、实现以及一个或多个DataSource。DataSource是与单个源一起工作的类:RemoteDataSource通过HTTP客户端调用API,LocalDataSource读写数据库。Repository通过构造函数接收DataSource(依赖注入)并选择要访问哪个源。例如,在请求用户列表时,Repository首先检查缓存,然后是数据库,最后是网络。

Repository模式的优点:数据源的更改(API变更、数据库迁移)不会影响UI层;通过替换Repository或DataSource进行单元测试;缓存对UI透明;无需更改屏幕逻辑即可在在线和离线模式之间切换。Android社区推荐Repository作为Clean Architecture中的必要层。

iOS中用Swift实现Repository模式:实现与示例

iOS实现 Repository基于Swift协议构建。Repository协议声明获取和保存数据的方法。实际实现通过初始化器注入——这允许在测试和SwiftUI预览中替换实现。DataSource也通过协议声明:Protocol RemoteDataSource、Protocol LocalDataSource。ViewModel或Interactor不知道具体实现——只知道Repository协议。

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
    }
}

依赖注入在iOS中通常通过工厂或DI容器(Swinject、Factory)进行配置。在测试中,UserRepository协议被返回预定义数据的mock实现替换。Async-await使代码保持同步和可读,无需闭包和委托。对于Combine响应式编程,Repository方法返回AnyPublisher而不是async throws。

Android中用Kotlin实现Repository模式:Flow示例

Android实现 Repository广泛使用Kotlin Coroutines和Flow进行异步工作。Google在官方Android架构指南(Android Architecture Components)中推荐Repository。Repository通过构造函数接收RemoteDataSource(Retrofit)和LocalDataSource(Room),ViewModel订阅来自Repository的Flow。Repository管理数据策略:先缓存、后网络,或始终网络,写入缓存。

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包装器在上面的示例中是Android的标准做法:sealed class Result通知ViewModel加载状态(Loading、Success、Error)。ViewModel通过collect订阅并更新StateFlow或LiveData。带Flow的Repository自动通知UI数据库中的更改——这是与一次性查询的关键区别,一次性查询中UI不会在不手动刷新的情况下知道更改。

DataSource:远程、本地和数据缓存

DataSource — 负责与特定数据源一起工作的类。RemoteDataSource使用HTTP客户端(URLSession、Retrofit、Ktor)从API获取数据。LocalDataSource与本地存储(CoreData、Realm、Room、UserDefaults、DataStore)一起工作。每个DataSource具有狭窄的职责:RemoteDataSource只知道API请求格式,LocalDataSource知道数据库模式。Repository组合它们,实现缓存策略。

DataSourceiOS平台Android平台来源
远程URLSession + CodableRetrofit + Moshi/GsonREST / GraphQL API
本地(数据库)CoreData、SwiftDataRoom、SQLDelight设备上的SQLite
本地(缓存)NSCache、UserDefaultsDataStore、EncryptedSP内存/磁盘
偏好设置UserDefaults、KeychainSharedPreferences、EncryptedSP设置、令牌

Repository中的缓存策略:Cache-First(先缓存,然后后台加载)、Network-Only(仅网络,用于支付屏幕)、Network-First-With-Cache-Backup(先网络,出错时使用缓存)。策略选择取决于场景:国家列表可以长期缓存,汇率——15分钟,钱包余额——仅来自网络。Repository实现策略并在不修改ViewModel或UI的情况下更改策略。

Repository模式与Service Layer:区别与选择

Repository和Service — 具有重叠功能的不同模式。Repository负责数据访问和缓存,返回数据模型。Service(或Interactor、Use Case)包含业务逻辑:验证、数据转换、协调多个Repository的调用。Service可以组合UserRepository、OrderRepository和NotificationRepository来处理订单。Repository不包含业务逻辑——仅CRUD和缓存。

何时选择Repository — 多源数据导航(API + 数据库 + 缓存)、offline-first架构、需要缓存和透明源切换。Repository在Clean Architecture中是必需的,Google推荐用于Android应用程序。在iOS的VIPER架构中,Repository的角色由Interactor层扮演,该层与Manager或Service交互以访问数据。

何时Service足够 — 具有单一数据源的简单应用程序、无写入的只读屏幕、无离线模式的项目。在这种情况下,DataSource直接由ViewModel或Presenter使用,Repository成为多余层。然而,在早期阶段添加Repository不需要大量成本,并且简化了未来添加缓存和测试的过程。

常见问题

Repository与DataSource有何不同?

DataSource — 与单一源(API、数据库、缓存)一起工作的类。Repository — 管理多个DataSource并提供统一接口的类。Repository决定从哪个DataSource获取数据并协调缓存。DataSource不知道其他源的存在,Repository不知道每个源的实现细节。

在iOS SwiftUI中需要Repository吗?

是的,Repository在SwiftUI中对于将数据与视图分离非常有用。ViewModel订阅Repository的Publisher,Repository管理缓存和同步。在简单应用中可以直接在ViewModel中使用URLSession,但为了可测试性和可扩展性,Repository更可取。Apple不强制使用此模式,但它与SwiftData和Network.framework兼容。

如何测试具有多个DataSource的Repository?

DataSource通过依赖注入替换为mock对象。测试创建一个mock RemoteDataSource(返回预定义JSON)和一个mock LocalDataSource(检查数据是否已保存)。Repository被隔离测试:检查缓存策略、错误处理和正确的调用顺序。对于集成测试,使用TestDispatcher(Kotlin)或MainActor.run(Swift)。

可以在没有接口(protocol)的情况下使用Repository吗?

可以,但不推荐。没有协议就无法在测试和预览中替换实现。在Kotlin中,Repository接口允许通过DI(Dagger、Hilt、Koin)替换实现。在Swift中,Repository协议对于测试async-await和Combine代码是必需的。例外情况——具有单一数据源且Repository不包含缓存逻辑的简单项目。

Repository上下文中的offline-first是什么?

Offline-first — 一种应用无需互联网即可使用本地数据运行的策略。Repository发挥关键作用:首先从本地DataSource返回数据,然后在后台与服务器同步。用户立即看到数据,Repository在从网络加载后更新数据。带Flow的Room在本地数据库数据更改时提供UI的响应式更新。

总结

  • Repository模式 — UI与数据源之间的抽象层
  • DataSource — API、数据库和缓存的独立类
  • 协议 — 测试和替换实现所必需
  • 缓存策略 — Cache-First、Network-Only、Network-First-With-Cache-Backup
  • iOS — 带协议的async-await或Combine
  • Android — Kotlin Flow + Room + Retrofit,Google推荐的方法
  • 测试 — 通过DI的mock DataSource,检查缓存策略

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读