1

我正在尝试构建一个演示器,它在某个时间段内计算一些事件,仅在第一次加载时显示加载,并在完成后更新 ui。因为可以通过多种方式(例如用户首选项)更新事件,所以我需要能够告诉演示者事件已更新并且必须再次刷新它们。这是我现在所拥有的:

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

主题是PublishSubjectInt 的。我onNext()在订阅后就这样做了,因为我希望数据在订阅后立即刷新。

上面的代码在我的单元测试中创造了奇迹,而且只有当我在连接了调试器的设备上运行它时。如果我只是运行它(没有任何调试器),它会到达该view.showLoading()部分,但永远不会provider.calculateEventsBetween(TimePeriod.aYearFrom(firstDay)因此 UI 被加载“卡住”。

有任何想法吗?

4

1 回答 1

6

您没有看到调用的消费者的可能原因是.subscribeOn(workScheduler). 通过将 this 应用于 a Subject,它本身没有实际用途,因为订阅 a 时没有订阅副作用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)

(1) 不是执行一次,而是doOnSubscribe确保当有工作要做时,主体的 onNext 发射将触发主线程上的加载指示器(假设 resultSchedulerAndroidSchedulers.mainThread处于非测试状态)。然后你会想要从主线程执行映射,因此 (2) 将项目移动到后台线程。映射完成后,生成的项目随后会在 (3) 处再次移动到主线程,您的视图可以在其中显示它。

于 2017-08-05T10:10:50.940 回答