【问题标题】:Using multiple .subscribe() statements with RxJava在 RxJava 中使用多个 .subscribe() 语句
【发布时间】:2017-06-19 18:51:00
【问题描述】:

我用于 BLE 外围设备的 Android 应用写入 2 个不同的设备特征并接收来自其他 2 个的通知。 RxAndroidBle 库的开发人员告诫不要在同一个 RxBleConnection 实例上进行多个订阅,但我看不到任何将所有这些 I/O 操作组合到单个 .subscribe() 中的实际方法,特别是因为其中一个通知是一个相当恒定的数据“水管”。

不知道更好,我只是将RxBleConnection 存储在一个变量中并在多个.subscribe()s 中使用它。据我所知,这一切正常。我调查了RxAndroidBle 库的ConnectionSharingAdapter,但是,虽然我分析了代码,但我不明白它比我的简单方法有什么好处(尽管我很想知道)。

一般来说,详细说明多个.subscribe()s 如何引入状态以及潜在的陷阱会有所帮助。问题:

  1. RxBleConnection 存储在一个变量中并将其用于多个.subscribe()s 有什么问题?
  2. 如果这是一个问题,ConnectionSharingAdapter 是如何解决的?
  3. 说多个订阅“引入状态”是什么意思,这怎么会导致问题?
  4. 是否有任何干净的方法可以将所有四个特征 I/O 操作组合成一个 .subscribe()(不会降低性能)?

【问题讨论】:

  • 这个问题有点太宽泛了——问库的开发者为什么他们建议不要多次订阅可能更容易。从纯 Rx 的角度来看,对同一(冷)流的多个订阅只有在一个主题(例如 RxJava 的 publish())上才是真正可能的,并且围绕主题使用的讨论是一个更大的问题,可能已经有了答案在这个网站和许多其他资源上。
  • 我确实问过他们这个问题,他们告诉我将讨论转移到 StackOverflow,所以我来了。
  • 应该改写问题本身,使其特定于RxAndroidBle 库。我对图书馆有同样的问题,并从关于图书馆的 github 讨论中得到了这里。 @罗伯特刘易斯

标签: android bluetooth-lowenergy rx-java reactive-programming rxandroidble


【解决方案1】:

RxBleConnection 存储在一个变量中并将其用于多个.subscribe()s 有什么问题? (...) 说多个订阅“引入状态”是什么意思,这怎么会导致问题?

这两个问题几乎是一样的。 RxBleConnection 是对 BLE 客户端与 BLE 服务器交换一些握手数据包的状态的抽象,之后客户端和服务器都被认为是连接的。不幸的是,由于各种原因,这种连接几乎在任何时候都可能中断(而且这种情况经常发生),RxBleConnection 的单个存储变量无法以反应方式轻松表达。

另一方面,一旦连接中断,观察RxBleDevice.establishConnection() 将向订阅者传播错误。虽然一旦连接断开,发出的RxBleConnection 的任何功能都不会起作用 - 连接的保存变量不会在问题发生时通知问题。

因此,如果用户将RxBleConnection 保存到变量中 - 它会引入变量可能处于的状态,并且用户负责传播(清除变量)稍后可能发生的错误。相反,订阅.establishConnection() 将在无法使用连接时发出异常。

正如许多程序员在实践中可能已经注意到的那样 - 管理状态是应用程序中最常见的错误来源。减少状态是降低错误风险的一种方法。

Jake Wharton 的 Devoxx 有一个出色(但相当先进)的演讲:Managing State with RxJava by Jake Wharton

如果这是一个问题,ConnectionSharingAdapter 是如何解决的?

.establishConnection() observable 不允许有多个同时订阅,因为 BLE 连接和通信的状态性质(请求-响应是一种众所周知的模式)并且有多个使用相同的 .subscribe()连接可能会导致相互干扰,而代码中没有清晰的痕迹。这就是为什么 BleAlreadyConnectedException 是为不遵循代码中所有使用 RxBleConnection 的地方的用户引入的。 ConnectionSharingAdapter 是作为有意识地决定在多个交互者之间共享单个连接的用户的助手而引入的。如果RxBleConnection 被破坏,ConnectionSharingAdapter 会将错误传播到所有Subscribers。

是否有任何干净的方法可以将所有四个特征 I/O 操作组合成一个 .subscribe()(不会降低性能)?

在大多数情况下,可以干净地组合许多 I/O。上面提到的谈话涉及这个话题。正确组合多个 I/O 会带来额外分配的成本,但在处理 BLE 时很少会出现问题,因为此通信通道的速度较低。

【讨论】:

  • 因为我的一个通知可以产生不间断的数据包流,这会对 BLE 的带宽造成负担,我认为为每个数据包建立和释放连接是行不通的。听起来像是使用ConnectionSharingAdapter 的案例,不是吗?
  • ConnectionSharingAdapter 只是标准 RxJava 运算符的简写(您可以通过检查类来检查)。只要可行,肯定应该保持连接。
  • 我也很困惑——由于用户输入,我的应用程序可以在不同时间发出无数的 BLE 命令。单个 subscribe() 方法怎么可能考虑到这一点?
  • 我刚刚向library repository 推送了一种更高级的响应式编程方法。随意检查一下——也许它会启发你如何只使用一个 .subscribe() 来处理你的用例。
猜你喜欢
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-04
  • 2021-06-16
  • 1970-01-01
  • 2021-02-19
相关资源
最近更新 更多