I have been trying for quite some time but I am unable to wrap my head around processing null values in RxJava & Kotlin
I have a Room database which returns a list of some entities (topics) from database. I need to pick one random item from the list or process different action if the list is empty.
After reading through various answers on SO and trying different approaches. I tried using Optional
:
fun getRandomTopic(): Single<Optional<Topic>> {
return topicDao.getAll().flatMap { topics ->
if (topics.isEmpty()) {
Single.just(Optional.ofNullable(null))
}
val index = (Math.random() * topics.size).toInt()
Single.just(Optional.of(topics[index]))
}
}
This function is observed in my activity:
viewModel.getRandomTopic()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result ->
if (result.isPresent) {
viewModel.currentTopic.postValue(result.get())
} else {
Toast.makeText(this, "No topic found", Toast.LENGTH_SHORT).show()
}
})
However, this always triggers either null pointer exception or IndexOutOfBoundsException
:
io.reactivex.exceptions.OnErrorNotImplementedException: Index: 0, Size: 0
at io.reactivex.internal.functions.Functions$14.accept(Functions.java:229)
at io.reactivex.internal.functions.Functions$14.accept(Functions.java:226)
at io.reactivex.internal.observers.ConsumerSingleObserver.onError(ConsumerSingleObserver.java:44)
at io.reactivex.internal.operators.single.SingleObserveOn$ObserveOnSingleObserver.run(SingleObserveOn.java:79)
at io.reactivex.android.schedulers.HandlerScheduler$ScheduledRunnable.run(HandlerScheduler.java:111)
at android.os.Handler.handleCallback(Handler.java:761)
at android.os.Handler.dispatchMessage(Handler.java:98)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6523)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)
Caused by: java.lang.IndexOutOfBoundsException: Index: 0, Size: 0
at java.util.ArrayList.get(ArrayList.java:411)
at cz.xxx.TopicViewModel$getRandomTopic$1.apply(TopicViewModel.kt:31)
at cz.xxx.TopicViewModel$getRandomTopic$1.apply(TopicViewModel.kt:17)
It seems that the condition
if (topics.isEmpty()) {
Single.just(Optional.ofNullable(null))
}
is somehow ignored and the statement continues even when the array is empty. What am I doing wrong here?
You have basically described where problem is. If you take a look at source code in Android Studio, expression Single.just(Optional.ofNullable(null))
is not evaluated as return value of the .flatMap()
.
Only last value of an lambda is. I recommend you to write down return statements like return@something
to make a code more clear and understandable. Solution?
fun getRandomTopic(): Single<Optional<Topic>> {
return topicDao.getAll().flatMap { topics ->
return@flatMap if (topics.isEmpty()) {
Single.just(Optional.ofNullable<Topic>(null))
} else {
val index = (Math.random() * topics.size).toInt()
Single.just(Optional.of(topics[index]))
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.