前言
关于Room的介绍和基本操作,请看我的这篇文章Room of Jetpack's Architecture Components
rxjava特点
先来简单介绍一下这几个属于RxJava的对象的特点。
- Completable:只有onComplete和onError方法,即是只有“完成”和“错误”两种状态,不会返回具体的结果。
- Single:其回调为onSuccess和onError,查询成功会在onSuccess中返回结果,需要注意的是,如果未查询到结果,即查询结果为空,会直接走onError回调,抛出EmptyResultSetException异常。
- Maybe:其回调为onSuccess,onError,onComplete,查询成功,如果有数据,会先回调onSuccess再回调onComplete,如果没有数据,则会直接回调onComplete。
- Flowable/Observable:这俩相信不用多介绍了,这是返回一个可观察的对象,每当查询语句查询的部分有变化时,都会回调它的onNext方法,直到Rx流断开。
使用Room的好处
- 更少的样板代码
- 编译时检查的SQL查询
- 异步和可观察查询的功能
所有这些都可以通过Room(来自架构组件的持久性库)来实现。异步查询返回LiveData或RxJava的Maybe,Single或Flowable。LiveData和Flowable的查询是可观察,它们可以在数据更改时自动进行更新,以确保UI响应数据库中的最新值。如果您已经在你的应用程序中使用RxJava 2,然后使用Room的Maybe,Single和Flowable将变得轻而易举。
考虑以下UI:用户能够查看和编辑其用户名。这和有关用户的其他信息一起保存在数据库中。这是插入,更新,删除和查询用户的方法。
Insert
Room集成RxJava允许以下相应的插入返回类型:
Completable— 插入完成后onComplete立即被调用Single<Long>或Maybe<Long>-onSuccess发送的值是插入的项目的行idSingle<List<Long>>或Maybe<List<Long>>-onSuccess发送的值是插入的项目的行id的列表
如果在插入数据时出错,Completable,Single和Maybe将在onError中发送异常。
@Insert
fun insert(user: User): Completable
@Insert
fun insert(user: User): Single<Long>
@Insert
fun insert(user: User): Maybe<Long>
@Insert
fun insert(vararg users: User): Single<List<Long>>
@Insert
fun insert(vararg users: User): Maybe<List<Long>>
@Query("INSERT INTO user VALUES(:firstName, :lastName, :age)")
fun insert(firstName: String, lastName: String, age: Int): Single<Long>
@Query("INSERT INTO user VALUES(:firstName, :lastName, :age)")
fun insert(firstName: String, lastName: String, age: Int): Maybe<Long>
- 返回的类型是
Long也只能是Long,否则无法通过编译。 - 返回的
Long值,是指的插入的行id。 - 使用
observeOn操作符指定Observer在哪个Scheduler上观察Observable,subscribeOn操作符指定Observable会运行在哪个Scheduler上。
Update/Delete
Room集成RxJava允许以下相应的插入返回类型:
Completable— 更新/删除完成后onComplete立即被调用Single<Integer>或Maybe<Integer>-其中onSuccess上发送的值是受更新/删除影响的行数
@Update/Delete
fun insert(user: User): Completable
@Update/Delete
fun insert(user: User): Single<Int>
@Update/Delete
fun insert(user: User): Maybe<Int>
@Update/Delete
fun insert(vararg users: User): Single<List<Int>>
@Update/Delete
fun insert(vararg users: User): Maybe<List<Int>>
@Query("UPDATE user SET firstname = :firstName WHERE age = :age")
fun updateFirstName(age: Int, firstName: String): Single<List<Int>>
@Query("UPDATE user SET firstname = :firstName WHERE age = :age")
fun updateFirstName(age: Int, firstName: String): Maybe<List<Int>>
注意:
- 返回的类型为
Integer也只能是Integer,否则无法通过编译。 - 返回的
Integer值,指的是该次操作影响到的总行数,比如该次操作更新了5条,就返回5
Query
为了从数据库中获取用户,我们可以在数据访问对象类(UserDao)中编写以下查询:
@Query(“SELECT * FROM Users WHERE id = :userId”)
User getUserById(String userId);
这种方法有两个缺点:
- 这是一个阻塞的同步调用
- 每次修改用户数据时,我们都需要手动调用此方法
Room提供了观察数据库数据和通过Rxjava的Maybe、Single、Flowable的帮助下执行异步查询的选项,如果您担心线程,Room可让您放心,并确保在主线程之外进行可观察的查询。您可以通过在observeOn方法中设置Scheduler来决定事件在哪个线程上向下游发出
Maybe
@Query(“SELECT * FROM Users WHERE id = :userId”)
Maybe<User> getUserById(String userId);
- 当数据库中没有用户并且查询不返回任何行时,
Maybe将onComplete。 - 当数据库中有一个用户时,
Maybe将触发**onSuccess**并onComplete。 - 如果
Maybe在onComplete后更新用户,则不会发生任何事情。
Single
@Query(“SELECT * FROM Users WHERE id = :userId”)
Single<User> getUserById(String userId);
- 当数据库中没有用户并且查询不返回任何行时,
Single将触发**onError(EmptyResultSetException.class)** - 当数据库中有一个用户时,
Single将触发**onSuccess**。 - 如果
Single在onComplete后更新用户,则不会发生任何事情。
Flowable/Observable
@Query(“SELECT * FROM Users WHERE id = :userId”)
Flowable<User> getUserById(String userId);
- 当数据库中没有用户并且查询不返回任何行,则
**Flowable***不会发送,既没有onNext,也不是onError。 - 当数据库中有一个用户时,
Flowable将触发**onNext**。 - 每次更新用户数据时,该
Flowable对象都会自动发出,从而使您可以基于最新数据来更新UI。

