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 Maybe
和 Single
的支持,所以现在你可以写类似
的东西
@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 {
}
})
正在尝试使用 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 Maybe
和 Single
的支持,所以现在你可以写类似
@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 {
}
})