onNext() 永远不会在 PublishSubject 上被调用

Posted

技术标签:

【中文标题】onNext() 永远不会在 PublishSubject 上被调用【英文标题】:onNext() never gets called on a PublishSubject 【发布时间】:2017-08-05 02:09:10 【问题描述】:

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

                      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 会“卡住”加载。

有什么想法吗?

【问题讨论】:

【参考方案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) 处再次移动到主线程,您的视图可以在其中显示它。

【讨论】:

成功了!非常感谢您的回复。这让我明白了很多哦,API 是如何工作的,因为我完全错了! 非常感谢您的回答,它表明了将正确的调度程序分配给observerOn() 的重要性

以上是关于onNext() 永远不会在 PublishSubject 上被调用的主要内容,如果未能解决你的问题,请参考以下文章

在 200 网络响应上调用 onError 而不是 onNext - RxJava,Retrofit

do(onNext:) 和 subscribe(onNext:) 有啥区别?

rxswift 绑定(onNext:VS 订阅(onNext:

Rx Swift 丢弃 .do(onNext: ) 我如何让它触发?

RxSwift 调用 bind 立即触发 vs subscribe(onNext: )

在 OnNext 运行时,我想删除所有传入的通知,除了最新的