@Entitydata class Dog ( @PrimaryKey val name: String, val cuteness: Int, val barkingVolume: Int)
为了从数据中获取一个包含所有小狗信息的总表,我们在 DAO 中编写如下 query 语句:@Query("SELECT FROM Dog")fungetAllDogs():List<Dog>
因为小狗的叫声,也就是字段 barkingVolume 会随着时间变化,并且我们想确保 UI 展示的内容是最新的因此我们希望,当数据库中的数据有变化时,可以通知到我们: 比如新增,删除,或者是更新了数据为了实现这个功能,我们通过更新 query 操作返回一个 Flow 对象@Query("SELECT FROM Dog")fungetAllDogs():Flow<List<Dog>>
就像这样,每当数据库中的数据有更新时,会重新派发存有小狗信息的总表例如,假设我们的数据库中存有如下数据:(Frida, 11, 3)(Bandit,12,5)
第一次调用 getAllDogs 时 Flow 派发的数据如下:如果小狗 Bandit 比较兴奋,那它的叫声也会变大,也就是字段 barkingVolume 更新为 6: (Bandit,12,6),这时候 Flow 会重新派发最新数据,所以整个列表被更新为:[(Frida, 11, 3), (Bandit, 12, 5)]
如果小狗 Bandit 比较兴奋,那它的叫声也会变大,也就是字段 barkingVolume 更新为 6: (Bandit,12,6),这时候 Flow 会重新派发最新数据,所以整个列表被更新为:[(Frida, 11, 3), (Bandit, 12, 6)]
现在我们来看一下获取单只小狗详细信息的操作,为了能够实时地获取小狗的最新数据,我们返回 Flow:@Query("SELECT FROM Dog WHERE name = :name")fungetDog(name:String):Flow<Dog>
如果我们调用 getDog("Frida"),Flow 会返回一个对象: (Frida, 11, 3)只要是数据库中的任意一个数据有更新,无论是哪一行数据的更改,那就重新执行 query 操作并再次派发 Flow,因此当小狗 Frida 有更新时我们会收到最新的数据同样道理,如果一个不相关的数据,比如小狗 Bandit 有更新时我们的 Flow 也会被派发,而且会收到与之前相同的数据: (Frida, 11, 3)这是因为 SQLite 数据库的内容更新通知功能是以表 (Table) 数据为单位,而不是以行 (Row) 数据为单位,因此只要是表中的数据有更新,它就触发内容更新通知Room 不知道表中有更新的数据是哪一个,因此它会重新触发 DAO 中定义的 query 操作您可以使用 Flow 的操作符,比如 distinctUntilChanged 来确保只有在当您关心的数据有更新时才会收到通知@Daoabstract class DoggosDao { @Query("SELECT FROM Dog WHERE name = :name") abstract fun getDog(name: String): Flow<Dog> fun getDogDistinctUntilChanged(name:String) = getDog(name).distinctUntilChanged()}
推荐您通过 Flow 进行可观察的读操作,以获取数据库中数据更新的通知您可以在您的整个应用中使用协程 (Coroutine) 和 Flow,而且还可使用 Jetpack 库中支持的其他协程功能,比如: 生命周期感知型协程范围 (lifecycle-aware coroutine scopes) 、挂起生命周期感知型协程 (suspend lifecycle-aware coroutines),也包括 Flow 转 LiveData 的操作后期会陆续更新更多Flow使用案例,敬请期待
文章转载自:谷歌开发者原创文章
(图片来源网络,侵删)
0 评论