前言
关于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。