RxJava Single and Room 错误处理问题

RxJava Single and Room Error handling Problem

我遇到了这个关于 Room 和 RxJava Single 的空数据库 return 的问题。 我知道我的数据库是空的,所以我希望在触发

时得到一个空的 return
@Query("SELECT * FROM Times WHERE timestamp = :timestamp")
fun getTimes(timestamp: String): Single<Times>

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

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

订户确实在调用 doOnError 方法,例如

E/Single: Returned null

但仍然return出现异常并崩溃

W/System.err: io.reactivex.exceptions.OnErrorNotImplementedException: Query returned empty result set: SELECT * FROM Times WHERE timestamp = ?

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

首先是针对您的问题的解决方案。由于版本 2.1.0-alpha01 Room 支持 Maybe return 类型,这非常适合为您的问题建模。

来自documentation

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

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

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

补充说明:

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

doOnError

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

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

默认值

如果目标是 return 一些默认值以防数据库为空,那么您将需要使用 onErrorReturn 以便链继续。查看 this blog post 了解更多信息。

空值

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