仓储模式
使用仓储模式将数据访问与 UI 分离。在 Room 数据库和网络 API 之间进行协调,将它们作为唯一事实来源。
仓储模式 是 CoddyKit 上的免费 Android Academy 课时。 这是第 4 节课,共 6 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Android Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Android Academy 课程共包含 6 节课。
为什么需要 Repository?
随着应用不断增大,ViewModel 中可能会塞满数据访问代码(Room 查询、Retrofit 调用、SharedPreferences 读取)。
Repository 模式 将所有数据访问集中到一个类的背后。ViewModel 只与 Repository 交互,不需要关心数据来自哪里。
架构分层
推荐的 Android 架构包含三层:
- UI 层 — Activity/Fragment 显示数据并发送用户事件
- ViewModel — 保存状态、处理事件并调用 Repository
- Repository — 从 Room(本地)或 Retrofit(远程)获取数据,并决定使用哪个数据源
一个简单的 Repository
创建一个封装 DAO 和远程 API 的 Repository 类:
class NoteRepository(private val dao: NoteDao) {
// Expose a Flow that emits whenever data changes
val allNotes = dao.getAllNotes()
suspend fun insert(note: Note) {
dao.insert(note)
}
suspend fun delete(note: Note) {
dao.delete(note)
}
suspend fun update(note: Note) {
dao.update(note)
}
}ViewModel 使用 Repository
ViewModel 从 Repository 获取数据,而不是直接从 DAO 获取:
class NoteViewModel(private val repo: NoteRepository) : ViewModel() {
val notes = repo.allNotes // Flow from Repository
fun addNote(title: String, body: String) {
viewModelScope.launch {
repo.insert(Note(title = title, body = body))
}
}
fun deleteNote(note: Note) {
viewModelScope.launch {
repo.delete(note)
}
}
}缓存优先策略
一种常见的 Repository 模式是缓存优先:立即显示本地缓存的数据,然后在后台从网络刷新:
- 1. 立即从 Room 发出缓存数据
- 2. 从 API 获取最新数据
- 3. 保存到 Room — Flow 会自动更新
这样既能快速加载,又能最终获得最新数据。
缓存优先实现
从网络刷新本地数据库:
class ProductRepository(
private val dao: ProductDao,
private val api: ProductApiService
) {
// Room Flow emits local data immediately
val products = dao.getAllProducts()
// Call this to sync with the server
suspend fun refresh() {
try {
val remoteProducts = api.getProducts()
dao.insertAll(remoteProducts) // overwrites local cache
} catch (e: Exception) {
// Network failed — cached data is still shown
}
}
}ViewModelFactory
当 ViewModel 有构造函数参数时,需要使用 ViewModelFactory 来创建它:
class NoteViewModelFactory(
private val repo: NoteRepository
) : ViewModelProvider.Factory {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
@Suppress("UNCHECKED_CAST")
return NoteViewModel(repo) as T
}
}
// In Activity:
val db = NoteDatabase.getInstance(this)
val repo = NoteRepository(db.noteDao())
val factory = NoteViewModelFactory(repo)
val viewModel = ViewModelProvider(this, factory)[NoteViewModel::class.java]使用 Hilt 进行依赖注入
在大型应用中,手动创建 Repository 和 ViewModel 实例会变得繁琐。Hilt(依赖注入)可以自动完成这些工作:
- 使用
@HiltViewModel、@Inject为类添加注解 - Hilt 会自动创建并提供依赖项
- 移除所有工厂样板代码
优点总结
Repository 模式带来以下优势:
- 可测试性 — 在单元测试中用伪实现替换真实 API
- 关注点分离 — ViewModel 不需要知道数据来自本地还是远程
- 唯一真实数据源 — Room 始终是数据源,API 只负责刷新它
- 灵活性 — 无需修改 ViewModel,即可添加缓存、分页或新的数据源
快速检查
Repository 在 Android 架构中的主要职责是什么?
回顾:Repository 模式
现在您已经了解推荐的 Android 架构:
- UI → ViewModel → Repository →(Room / Retrofit)
- Repository 是唯一真实数据源
- 缓存优先:立即显示本地数据,在后台刷新
- 当 ViewModel 有构造函数参数时,使用 ViewModelFactory
- Hilt 可在大型应用中自动完成依赖注入
最后一门课程:网络与完善——Retrofit、图像和发布。
常见问题解答
「仓储模式」课时是免费的吗?
是的 — 「仓储模式」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Android Academy 课程的其余内容,请升级到 CoddyKit PRO。 Android Academy 课程共包含 6 节课。
「仓储模式」这节课中我会学到什么?
使用仓储模式将数据访问与 UI 分离。在 Room 数据库和网络 API 之间进行协调,将它们作为唯一事实来源。 你通过在浏览器中直接运行的动手代码来练习 Android Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 Android Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 Android Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 4 节课,共 6 节。
「仓储模式」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 Android Academy 课中编写并运行代码吗?
能。每节 Android Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。