为什么必须在 `single` 之前调用 `toBlocking`?

Why is it necessary to call `toBlocking` before `single`?

我正在探索 Swagger 生成的 Java API。在生成的客户端文件中,我看到两个这样的方法:

public Observable<UserAccountView> createUserAccount(/* params omitted  */) {
   /* body omitted */
}

public UserAccountView createUserAccountSynchronously(/* params omitted */) {
  return createUserAccount(/*params*/).toBlocking.single();
}

我已经阅读了 RxJava 文档和相关资源,但由于我是新手,所以我仍然认为这里不需要 toBlocking——不是 blocking/non-blocking单身就失去意义了?有阻塞单这样的东西吗?

显然我没有完全理解这两种方法之间的关系。我认为 single() 是在取消订阅之前从可观察对象中提取单个事件。为什么需要 toBlocking 才能做到这一点?

存在 toBlocking() 调用,因此方法 returns UserAccountView 而不是 Observable<UserAccountView>toBlocking() converts the Observable into a BlockingObservable, and calling BlockingObservable.single() returns BlockingObservable 发出的任何项目,只要它在完成前只发出一项(多于或少于一项都会导致发出错误)。

如果你在 RxJava1 中调用 Observable.single() 而不将其转换为 BlockingObservable,它将 return 一个仅发出单个项目的 Observable<UserAccountView>,如果Observable 在发出一项后完成。在 RxJava2 中,API 得到了改进,因此等价的运算符 Observable.singleOrError()、return 变成了 Single<UserAccountView>.

Blocking/non-blocking 不会失去对 Single 的意义(或者在这种情况下,Observable 只会发出一个项目)。根据您设置调度程序的方式(例如使用 subscribeOn()observeOn() 或使用 Scheduler 的运算符),您可以使用 Single/Observable 仅在某个工作线程中进行处理后异步发出其一项。因此,如果 createUserAccount() 的调用者是应用程序主线程中的 运行,则 Observable<UserAccountView> 可以立即 return,并在几秒钟,没有主线程被阻塞。另一方面,使用 createUserAccountSynchronously() 将阻塞主线程,直到 Observable<UserAccountView> 发出它的一个项目。

通常在反应式应用程序中,您会避免使用 toBlocking(),但有时您需要在反应式世界和非反应式、阻塞式世界之间架起一座桥梁,这就是 toBlocking() 可以发挥作用的地方。