實戰 | 在 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閱讀 227,748評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,165評論 3 414
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,595評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,633評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,435評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,943評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,035評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,175評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,713評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,599評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,788評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,303評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,034評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,412評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,664評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,408評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,747評論 2 370

推薦閱讀更多精彩內容