我正在将我的应用程序转换为房间数据库,并尝试遵循基于“带视图的房间”的谷歌架构最佳实践。
我无法从干净架构的角度理解存储库。
Words 数据库示例仅包含一个表和一个使用它的视图,使其成为一个简单的 HelloWorld 示例。但让我们从那开始。
有一个显示单词列表的视图。因此,所有单词都需要从数据库中读取并显示。所以我们有一个 MainActivity 和一个要连接的数据库。
- 实体词
- WordDao 访问数据库
- WordViewModel:为了将活动生命周期与数据生命周期分开,使用了 ViewModel。
- WordRepository:因为数据可能保存在数据库或云中或任何引入存储库以处理数据来自何处的决策。
- 活动与视图
如果在数据更改时更新视图会很好,因此使用 LiveData。
这反过来意味着,存储库正在为完整表提供 LiveData:
// LiveData gives us updated words when they change.
val allWords: LiveData<List<Word>>
对于单一视图来说,这一切都很好。
现在来回答我关于扩展这个概念的问题。
让我们假设,单词表有两列“word”和“last_updated”作为时间字符串。
为了更容易比较时间字符串需要转换为毫秒,所以我有一个函数。
问题:在哪里放置有趣的 queryMaxServerDateMS() 以获得最大值(last_updated)?
/**
* @return Highest server date in table in milliseconds or 1 on empty/error.
*/
fun queryMaxServerDateMS(): Long {
val maxDateTime = wordDao.queryMaxServerDate()
var timeMS: Long = 0
if (maxDateTime != null) {
timeMS = parseDateToMillisOrZero_UTC(maxDateTime)
}
return if (timeMS <= 0) 1 else timeMS
}
对我来说,将它放入 WordRepository 是很自然的。
第二个要求:后台作业更新数据库中的单词列表。
假设我现在想要一个定期安排的后台作业,它检查服务器是否有新条目并将它们下载到数据库。该应用程序可能未打开。
这个问题只是转达了上面queryMaxServerDateMS的问题。
该作业将首先检查是否通过询问服务器是否存在比最大已知条目更新的条目来创建新条目。
所以我需要获取一个新类 WordRepository,进行查询,获取 max last_update 并询问服务器。
但是:我不需要后台作业中的 LiveData,当 val repositoy = WordRepository 读取完整的表时,这是不必要的,而且会耗费时间、内存和电池。
我还可以想到许多不同的片段,它们需要单词表的一些数据,但从不需要完整数据,想想列出一个产品的产品详细信息屏幕。
所以我可以将它移到另一个存储库或 DbHelper 中,但是你想调用它。
但最后我想知道,如果我使用 LiveData,它需要 View、ViewModel 和 Repository 紧密耦合在一起:
问题:我是否需要为每个活动/片段创建一个存储库,而不是为每个表创建一个更符合逻辑的存储库?