实战 | 在 Room 中使用 Flow

△ Room 中对 Flow 的支持

Jetpack Room 对协程的支持越来越丰富: Room 2.1 版本增加了对协程的支持,并加入了一次性 (one-shot) 的读写操作,Room 2.2 我们通过 Flow 为读操作加入了可观察性,当数据库中的数据有变化时它可以使您收到通知。

△ Room 支持异步 query 操作

Flow 实战

假设我们有一个记录小狗信息的数据库,它的 name 字段是主键 (primary key),所以在数据库中不可能同时有两个 name 字段相同的数据,也就是每只小狗都是唯一的。

@Entity
data class Dog (
    @PrimaryKey val name: String,
    val cuteness: Int,
    val barkingVolume: Int
)

为了从数据中获取一个包含所有小狗信息的总表,我们在 DAO 中编写如下 query 语句:

@Query("SELECT * FROM Dog")
fun getAllDogs(): List<Dog>

因为小狗的叫声,也就是字段 barkingVolume 会随着时间变化,并且我们想确保 UI 展示的内容是最新的。因此我们希望,当数据库中的数据有变化时,可以通知到我们: 比如新增,删除,或者是更新了数据。

为了实现这个功能,我们通过更新 query 操作返回一个 Flow 对象。

@Query("SELECT * FROM Dog")
fun getAllDogs(): Flow<List<Dog>>

就像这样,每当数据库中的数据有更新时,会重新派发存有小狗信息的总表。例如,假设我们的数据库中存有如下数据:

(Frida, 11, 3)
(Bandit, 12, 5)

第一次调用 getAllDogs 时 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")
fun getDog(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 来确保只有在当您关心的数据有更新时才会收到通知。

@Dao
abstract 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 的案例,可参考我们之前发布的一篇基于 Android 开发者峰会应用的最佳实践 的文章。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容