subscribeOn 和 observeOn 应该只由最终订阅者调用吗?

Should subscribeOn and observeOn only be invoked by the final subscriber?

Rx 简介Scheduling and Threading 部分说

the use of SubscribeOn and ObserveOn should only be invoked by the final subscriber

它还表示,在 UI 应用程序中,表示层(通常是最终订阅者)应该是调用这些方法的层。

我想知道这个建议是否可靠,因为我看到有些情况下这样做并不方便:

  1. 首先,我认为表示层不应该决定应该在何处订阅来自数据层的 Observable。在我看来,表示层应该不知道数据是来自数据库、来自 REST API 还是来自内存。为此,数据层在返回Observable前调用subscribeOn()比较方便,传递IO Scheduler或者直接的Scheduler是方便的。
  2. 如果表示层从某个服务或用例中获取 Observable(后者又从数据层获取)并且此服务决定它需要在某个计算调度程序中处理流,那么表示层为什么要处理关心这个?
  3. 最初来自 UI 的流怎么办,因此需要在 UI 线程中订阅它。然后它会被发送到一些服务做一些工作,最后回到表现层在UI线程中观察。这将需要 UI 流成为 subscribeOn() UI 调度程序,然后 observeOn() 其他调度程序,最后 observeOn() UI 调度程序。在这种情况下,只能在最终订阅者中调用 subscribeOn()observeOn() 意味着流只能在 UI 线程中处理。

为什么我应该牺牲我的应用程序的体系结构并忽略 Rx 通过仅由最终订阅者调用这两个方法来轻松切换线程的能力?

  1. 表示层本身并不关心可观察对象来自何处,但它确实关心它是否可能锁定 UI 线程。因此表示层必须采取预防措施来防止这种情况发生。这是一个带有安全层的幸福无知的案例。

  2. 表示层不关心。它只是想确保它自己没有被阻止。

  3. 如果流来自 UI 则需要很长时间来处理流的所有者 应该 认真对待这一点,并确保它在 non-UI 调度程序上进行处理。然后 UI 必须确保它返回到 UI 线程,如果它需要在那里被消耗的话。如果处理速度快就无所谓了。

很高兴看到您已阅读本书并花时间挑战其中的一些指导。

我给出这个指导的原因是因为

  1. 并发很难,有一个简单的规则可以帮助 团队 产生更好的代码
  2. 并发很难,有一个地方来定位您的并发问题可以让您的 stack/layering 有更好的心智模型,并且应该可以简化测试。在你的应用程序中引入并发的层越多,越糟糕
  3. 阻塞 UI 线程可不是什么好消息。尽快离开 UI-Thread,然后尽可能晚地延迟返回 UI 的任何数据处理是可取的。此模式旨在实现该目标。

这些显然是我的意见,但我已经看到这些简单的指南有助于清理数十个项目的代码、减少代码库、提高测试能力、提高可预测性并在许多情况下显着提高性能。

遗憾的是,很难将这些项目的案例研究放在一起,因为它们中的大多数都受到 NDA 的保护。

我很想知道它如何为您工作或您如何应用替代模式。