onNext() никогда не вызывается для PublishSubject

Я пытаюсь построить презентатор, который вычисляет некоторые события за определенный период времени, показывает загрузку только при первой загрузке и обновляет пользовательский интерфейс, когда это будет сделано. Поскольку события могут обновляться несколькими способами (например, пользовательскими настройками), я должен быть в состоянии сообщить докладчику, что события были обновлены и что он должен обновить их снова. Вот что у меня сейчас есть:

                      subject
                            .map<List<UpcomingRowViewModel>> {
                                provider.calculateEventsBetween(TimePeriod.aYearFrom(firstDay))
                            }
                            .doOnSubscribe {
                                view.showLoading()
                            }
                            .observeOn(resultScheduler)
                            .subscribeOn(workScheduler)
                            .subscribe { upcomingRowViewModels ->
                                view.display(upcomingRowViewModels)
                            }
                      subject.onNext(TRIGGER)

Предметом является PublishSubject Инт. Я делаю onNext() сразу после подписки, потому что я хочу, чтобы данные обновлялись сразу после их подписки.

Приведенный выше код творит чудеса в моих модульных тестах, а также только тогда, когда я запускаю его на устройстве с подключенным отладчиком. Если я просто запускаю его (без какого-либо отладчика), он достигает view.showLoading() часть, но никогда provider.calculateEventsBetween(TimePeriod.aYearFrom(firstDay) Таким образом, пользовательский интерфейс застревает с загрузкой.

Есть идеи?

1 ответ

Решение

Вероятная причина, по которой вы не видите звонка .subscribeOn(workScheduler), Применив это к Subjectкоторый сам по себе не имеет практического применения, так как при подписке на SubjectВы задерживаете подписку на Subject достаточно того, что onNext колл не найдет ни одного наблюдателя в этот момент.

То, что вы, вероятно, хотите, что-то вроде этого:

subject
    .observeOn(resultScheduler)             // <--------------- (1)
    .doOnNext {
        view.showLoading()
    }
    .observeOn(workScheduler)               // <--------------- (2)
    .map<List<UpcomingRowViewModel>> {
        provider.calculateEventsBetween(
            TimePeriod.aYearFrom(firstDay))
    }
    .observeOn(resultScheduler)             // <--------------- (3)
    .subscribe { upcomingRowViewModels ->
        view.display(upcomingRowViewModels)
    }
subject.onNext(TRIGGER)

Вместо doOnSubscribe, который выполняется один раз, (1) гарантирует, что когда есть работа, эмиссия onNext субъекта вызовет индикатор загрузки в главном потоке (при условии, что resultScheduler равен AndroidSchedulers.mainThread в не тестах). Затем вы захотите выполнить сопоставление основного потока и, таким образом (2) переместить элемент в фоновый поток. Как только сопоставление произошло, полученный элемент снова перемещается в основной поток в (3), где ваш вид может отобразить его.

Другие вопросы по тегам