RxJava Single 和 Room 错误处理问题

mus*_*off 4 android exception rx-java rx-android android-room

我遇到了有关 Room 和 RxJava Single 的空数据库返回的问题。我知道我的数据库是空的,所以我期望在触发时得到空返回

@Query("SELECT * FROM Times WHERE timestamp = :timestamp")
fun getTimes(timestamp: String): Single<Times>
Run Code Online (Sandbox Code Playgroud)

问题是当我如下调用这个函数时

timeDao.getTimes("1398332113")
       .observeOn(AndroidSchedulers.mainThread())
       .subscribeOn(Schedulers.io())
       .doOnError { Log.e("Single", "Returned null") }
       .doOnSuccess { result -> times = result}
       .subscribe()
Run Code Online (Sandbox Code Playgroud)

订阅者确实正在调用doOnError类似的方法

E/Single:返回空

但仍然返回异常并崩溃

W/System.err: io.reactivex.exceptions.OnErrorNotImplementedException: 查询返回空结果集: SELECT * FROM Times WHERE timestamp = ?

我在StackOverflow上看到了很多类似的问题,但找不到答案。我做错了什么?

Lor*_*nMK 5

首先是您问题的解决方案。由于2.1.0-alpha01Room 版本支持Maybe返回类型,因此非常适合对问题进行建模。

文档中:

Maybe 使用以下顺序协议运行:onSubscribe (onSuccess | onError | onComplete)?

当您的项目位于数据库中时:onSuccess将使用数据进行调用。如果数据库为空onComplete将被调用。onError是不言自明的。

Single将 Dao 类中的替换Maybe为 即可。

进一步说明:

timeDao.getTimes("1398332113")
       .observeOn(AndroidSchedulers.mainThread())
       .subscribeOn(Schedulers.io())
       .doOnError { Log.e("Single", "Returned null") }
       .doOnSuccess { result -> times = result}
       .subscribe()
Run Code Online (Sandbox Code Playgroud)

发生错误时

doOnError如果出现错误,将会执行 lambda,但它仍然会在链中发出错误。您的程序崩溃是因为它不处理错误(为subscribe()空)。

你可以采取措施subscribe({/* doing nothing for success */}, {e -> Log.e("TAG", "Empty DB")})来防止崩溃。

默认值

如果目标是在数据库为空的情况下返回一些默认值,那么您将需要使用onErrorReturn以便链继续。请查看这篇博文以获取更多信息。

空值

默认值不能为 null,Reactive Streams 规范(RxJava2 实现它)不支持 null 值。