Android RxJava 处理空查询结果的房间

Android Room with RxJava handle empty query result

正在尝试使用 RxJava 适配器测试新的 Android Room librarty。如果我的查询 returns 0 个来自数据库的对象,我想处理结果:

这里是 DAO 方法:

@Query("SELECT * FROM auth_info")
fun getAuthInfo(): Flowable<AuthResponse>

以及我的处理方式:

database.authDao()
    .getAuthInfo()
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .switchIfEmpty { Log.d(TAG, "IS EMPTY") }
    .firstOrError()
    .subscribe(
            { authResponse -> Log.d(TAG, authResponse.token) },
            { error -> Log.d(TAG, error.message) })

我的数据库是空的,所以我希望 .switchIfEmty() 可以工作,但是 none 的处理方法正在触发。既不是 .subscribe() 也不是 .switchIfEmpty()

switchIfEmpty 作为参数 a Publisher<AuthResponse>。通过 SAM 转换,你给定的匿名函数变成了这个 class。但是它不遵循 Publisher 预期的行为,因此它不会按预期工作。

Flowable.empty().doOnSubscribe { Log.d(TAG, "IS EMPTY") } 之类的正确实现替换它,它应该可以工作。

Db Flowables 是可观察的(所以如果数据库发生变化它们会继续调度)所以它永远不会完成。您可以尝试返回 List<AuthResponse>。我们考虑过向后移植一个可选的但决定不这样做,至少现在是这样。相反,我们可能会在不同的已知库中添加对 Optional 的支持。

在版本 1.0.0-alpha5 中,room 添加了对 DAOs MaybeSingle 的支持,所以现在你可以写类似

的东西
@Query("SELECT * FROM auth_info")
fun getAuthInfo(): Maybe<AuthResponse>

您可以阅读更多相关信息here

您可以对结果使用一些包装器。例如:

public Single<QueryResult<Transaction>> getTransaction(long id) {
            return createSingle(() -> database.getTransactionDao().getTransaction(id))
                    .map(QueryResult::new);
}

    public class QueryResult<D> {
            public D data;
            public QueryResult() {}

            public QueryResult(D data) {
                this.data = data;
            }

            public boolean isEmpty(){
                return data != null;
            }
 }

protected <T> Single<T> createSingle(final Callable<T> func) {
            return Single.create(emitter -> {
                try {
                    T result = func.call();
                    emitter.onSuccess(result);

                } catch (Exception ex) {
                    Log.e("TAG", "Error of operation with db");
                }
            });
}

并像 'Single' 一样使用它,在这种情况下,您无论如何都会得到结果。使用:

dbStorage.getTransaction(selectedCoin.getId())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(r -> {
                         if(!r.isEmpty()){
                           // we have some data from DB
                         } else {
                       }
                    })