在readCharacteristic()等函数中对Observable与Single的困惑感到困惑

时间:2018-03-13 19:08:42

标签: rx-java2 rxandroidble

RxAndroidBle的RxJava2版本中,函数readCharacteristic()writeCharacteristic()返回Single<byte[]>

读取特征的示例代码是: device.establishConnection(false).flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(characteristicUUID))

但是flatMap()的文档说映射函数应该返回ObservableSource。在这里,它返回Single。这怎么办?

更新:我查看了使用.single().singleOrError()等运算符的可能性,但它们似乎都要求上游发出一个项目然后完成。但是establishConnection()并没有完成。 (这是我建议将establishConnection()重新设想为Maybe的原因之一,并提供其他一些方式来断开连接,而不仅仅是取消订阅。)

3 个答案:

答案 0 :(得分:2)

你完全正确,这个例子无法编译。它可能是RxJava1版本的遗留物,其中Single不存在 具有相同结果的简单修复是使用RxJava2 flatMapSingle例如:

device.establishConnection(false)
            .flatMapSingle(rxBleConnection -> rxBleConnection.readCharacteristic(characteristicUUID))

flatMapSingle接受Single作为返回值,并将输入Single的成功值映射到上游Observable的发射。

关键是,RxJava具有更具体的Observable类型,它们暴露了此Observable期望的可能的一系列排放。现在有些方法返回Single,因为这是它们的流(readCharacteristic())的逻辑运算,有些是Observable,因为它们将发出多于单个发射(establishConnection() - 连接状态可以随着时间的推移而改变。) 但是RxJava2还提供了许多运算符来在不同类型之间进行转换,这实际上取决于您的需求和场景。

答案 1 :(得分:0)

谢谢Rob!

事实上,README已被弃用,并且需要一些拉皮条。请看看它现在好不好。

答案 2 :(得分:0)

我想我找到了我想要的答案。关键点: Single.fromObservable(observableSource)在收到observableSource第二个项目之前不做任何事情!假设它收到的第一个项是有效的发射,那么如果第二个项是:

  • onComplete(),它将第一项传递给onSuccess();
  • onNext(),它发出IndexOutOfBoundsException信号,因为Single不能发出多个项目;
  • onError(),它可能会将错误转发到下游。

现在,device.establishConnection()是一项,未完成 Observable。它发出的RxBleConnecton是flatMapped到Single readCharacteristic()。但是(另一个问题),flatMapSingle订阅这些Single并将它们组合成Observable,直到源establishConnection()完成后才会完成。但来源并没有完成!因此,我们尝试创建的Single不会发出任何内容,因为它没有收到必要的 second 项。

解决方案是强制在第一个(也是唯一的)项目之后生成onComplete(),这可以使用take(1)来完成。这将满足我们正在创建的Single,并使其发出我们感兴趣的特征值。希望这很清楚。

代码:

Single<byte[]> readCharacteristicSingle( RxBleDevice device, UUID characteristicUUID ) {
    return Single.fromObservable(
            device.establishConnection( false )
                    .flatMapSingle( connection -> connection.readCharacteristic( characteristicUUID ) )
                    .take( 1L )  // make flatMapSingle's output Observable complete after the first emission
                                 // (this makes the Single call onSuccess())
    );
}