我正在尝试构建一个在一段时间内计算某些事件的演示者,仅在第一次加载时显示加载,并在完成后更新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)
主题是Int的PublishSubject
。我在订阅后立即执行onNext()
,因为我希望在订阅数据后立即刷新数据。
上面的代码在我的单元测试中起作用,并且只有当我在连接了调试器的设备上运行它时。如果我只是运行它(没有任何调试器),它会到达view.showLoading()
部分,但永远不会到达provider.calculateEventsBetween(TimePeriod.aYearFrom(firstDay)
,因此UI会因加载而“卡住”。
有什么想法吗?
答案 0 :(得分:4)
您没有看到被叫消费者的可能原因是.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),您的视图可以显示它。