Android:使用 Room 和 RxJava 检查对象是否存在于数据库中

Android: Check if object is present in database using Room and RxJava

我正在使用 Room 作为 ORM,这是我的 Dao 接口:

@Dao
interface UserDao {
    @Query(value = "SELECT * FROM User LIMIT 1")
    fun get(): Single<User?>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    fun add(profile: User)
}

另一方面,我在 Repository 中有一个方法应该检查用户是否登录,这是实现代码:

override fun isUserLogin(): Single<Boolean> = userDao
            .get().async()
            .onErrorReturn { null }
            .map { it != null }

如果没有行匹配查询,Room 将抛出以下异常:

Query returned empty result set: SELECT * FROM User LIMIT 1

在这种情况下,我想 return null,但是当我执行代码时,它会抛出异常并显示以下消息:

Value supplied was null

我不能使用 Optional 因为 Dao 是 returning Single<User?> 所以 onErrorReturn 应该 return 相同的类型。

如何在不修改 Dao 的情况下判断用户是否存在?

使用 Maybe,它可以准确地模拟期望 0 个结果、1 个结果或异常的响应。

如果您将 DAO 更改为 return Flowable 用户列表,您可以通过检查列表的大小将其映射为布尔值。

@Query(value = "SELECT * FROM User LIMIT 1")
fun get(): Flowable<List<User>> 

例如

fun isUserLogin(): Single<Boolean> = userDao
    .get()
    .flatMapSingle { Single.just(it.size == 1) }
    .onErrorReturn { false }
    .first(false)

我认为除了 Android 和 Room 之外,正确的方法是在查询中使用 COUNT

@Query("SELECT COUNT(*) from User")
fun usersCount() : Single<Int>

它将 return table 中的行数,如果它是 0 你知道数据库中没有用户,所以。

override fun isUserLogin(): Single<Int> = userDao
            .usersCount()
            .async()
            .map { it > 0 }

如果你真的想以丑陋的方式做到这一点:

@Query(value = "SELECT * FROM User LIMIT 1")
fun get(): Single<User>

不要使用可空类型,这是没有意义的。然后映射到Boolean并处理异常:

override fun isUserLogin(): Single<Boolean> = userDao
        .get()
        .async()
        .map { true }
        .onErrorReturn { false }