Излучить нуль из Observable в RxJava - PullRequest
0 голосов
/ 27 января 2019

Я пытался в течение достаточно долгого времени, но я не могу обернуться, обрабатывая нулевые значения в RxJava & Kotlin

У меня есть база данных Room, которая возвращает список некоторых сущностей (тем) из базы данных,Мне нужно выбрать один случайный элемент из списка или обработать другое действие, если список пуст.

После прочтения различных ответов на SO и пробования различных подходов.Я пытался использовать 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]))
        }
    }

Эта функция наблюдается в моей деятельности:

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()
                    }
                })

Однако, это всегда вызывает либо исключение нулевого указателя, либо 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)

Кажется, что условие

if (topics.isEmpty()) {
       Single.just(Optional.ofNullable(null))
}

каким-то образом игнорируется, и оператор продолжается, даже когда массив пуст.Что я здесь не так делаю?

1 Ответ

0 голосов
/ 27 января 2019

Вы в основном описали, где проблема. Если вы посмотрите на исходный код в Android Studio, выражение Single.just(Optional.ofNullable(null)) не оценивается как возвращаемое значение .flatMap().

AS screenshot

Только последнее значение лямбды - это. Я рекомендую вам записывать операторы возврата, например return@something, чтобы сделать код более понятным и понятным. Решение

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]))
        }
    }
}
...