I am having this issue regarding empty database return with Room and RxJava Single. I know that my database is empty, so I am expecting to get an empty return when I trigger
@Query("SELECT * FROM Times WHERE timestamp = :timestamp")
fun getTimes(timestamp: String): Single<Times>
The problem is when I call this function as below
timeDao.getTimes("1398332113")
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError { Log.e("Single", "Returned null") }
.doOnSuccess { result -> times = result}
.subscribe()
The subscriber is indeed calling doOnError
method like
E/Single: Returned null
but still returning an exception and crash
W/System.err: io.reactivex.exceptions.OnErrorNotImplementedException: Query returned empty result set: SELECT * FROM Times WHERE timestamp = ?
I have seen so many similar questions on StackOverflow, but couldn't find an answer. What am I am doing wrong?
First a solution for your problem. Since version 2.1.0-alpha01
Room supports the Maybe
return type which is perfect for modelling your problem.
From the documentation:
The Maybe operates with the following sequential protocol: onSubscribe (onSuccess | onError | onComplete)?
When your the item is in the db: onSuccess
will be called with the data. If the db is empty onComplete
will be called. onError
is self explanatory.
Replacing the Single
with Maybe
in the Dao class will work.
Further notes:
timeDao.getTimes("1398332113")
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.doOnError { Log.e("Single", "Returned null") }
.doOnSuccess { result -> times = result}
.subscribe()
doOnError
will execute the the lambda in case of en error, but it will still emit the error down the chain. Your program crashes because it doesn't handle errors (the subscribe()
is empty).
You could do subscribe({/* doing nothing for success */}, {e -> Log.e("TAG", "Empty DB")})
to prevent the crash.
If the goal is to return some default value in case the DB is empty then you will want to use onErrorReturn
so that the chain continues. Take a look at this blog post for more info.
The default value can't be null, the Reactive Streams specification (RxJava2 implements it) doesn't support null values.