rx-java – 如何以线性方式连接两个可观察的操作(首先执行此操作,然后完成第二个操作)?

Polidea发布了一个新的handy library called RxAndroidBle,这对于处理很多问题非常有用,当你使用香草蓝牙API时.

在解释更多之前,想法是让POJO模型具有设备向我发送(或我查询)的所有最新值(在这种情况下由Map对象表示):

如果我想收到有关多个特征通知的通知,我可以这样做:

final UUID serviceUuid = // your service UUID
final Map<UUID, byte[]> genericModel = new HashMap<>();
final Observable<RxBleConnection> connectionObservable = // your connectionObservable

connectionObservable
        .flatMap(connection -> 
                connection.discoverServices()
                        .flatMap(services -> services.getService(serviceUuid).map(BluetoothGattService::getCharacteristics)) // get characteristics you're interested in
                        .flatMap(Observable::from) // deal with every characteristic separately
                        .flatMap(characteristic -> connection
                                        .setupNotification(characteristic) // setup notification for each
                                        .flatMap(observable -> observable), // to get the raw bytes from notification
                                Pair::new) // merge characteristic with byte[] to keep track from which characteristic the bytes came
        )
        .subscribe(
                pair -> genericModel.put(pair.first.getUuid(), pair.second),
                throwable -> { /* handle errors */}
        );

现在,当我连接到设备时,通知正在更新POJO对象(此特定示例中的Map).

如果我想读取值,我可以执行以下操作:

 connectionObservable.flatMap(connection ->
    connection.discoverServices()
        .flatMap(services -> services.getService(SERVICE_ID).map(BluetoothGattService::getCharacteristics))
        .flatMap(Observable::from)
        .filter(characteristic -> BleUtils.hasReadProperty(characteristic.getProperties()))
        .flatMap(connection::readCharacteristic, Pair::new)
)
    .subscribe(
            pair -> genericModel.put(pair.first.getUuid(), pair.second),
            throwable -> { /* handle errors */}
    );

我的主要问题是:

我想在第一个连接上:读取一些具有读取属性的特征,并且只有在订阅了具有notification属性的通知之后.这是连接操作.我怎么能做到这一点?

问题是,当我执行读取的第一部分时,observable读取那些特性属性但不会发出doOnComplete方法,因为等待更多因此我无法启动或编写下一个订阅和收听更改的操作.

我肯定知道具有读取属性的特性量,但我想以通用的方式进行(即如果我有7或15个我想读的特性并不重要,我只想读它们全部,写下pojo值,然后开始收听通知).

也许选择是组成一个可观察到的成功读数的观察者,然后开始收听通知.

如何实现这一目标的最佳反应方法是什么?

为了让你处于这种情况,这是the original thread that spawned this question.

最佳答案
要达到你想要的效果,你可以采取多种方式.其中之一是:

    final UUID serviceUuid = // your service UUID
    final Map<UUID, byte[]> genericModel = new HashMap<>();
    final Observable<RxBleConnection> connectionObservable = // your connectionObservable

    connectionObservable
            .flatMap( // get the characteristics from the service you're interested in
                    connection -> connection
                            .discoverServices()
                            .flatMap(services -> services
                                    .getService(serviceUuid)
                                    .map(BluetoothGattService::getCharacteristics)
                            ),
                    Pair::new
            )
            .flatMap(connectionAndCharacteristics -> {
                final RxBleConnection connection = connectionAndCharacteristics.first;
                final List<BluetoothGattCharacteristic> characteristics = connectionAndCharacteristics.second;
                return readInitialValues(connection, characteristics)
                        .concatWith(setupNotifications(connection, characteristics));
            })
            .subscribe(
                    pair -> genericModel.put(pair.first.getUuid(), pair.second),
                    throwable -> { /* handle errors */}
            );

哪里:

private Observable<Pair<BluetoothGattCharacteristic, byte[]>> readInitialValues(RxBleConnection connection,
                                                                                List<BluetoothGattCharacteristic> characteristics) {
    return Observable.from(characteristics) // deal with every characteristic separately
            .filter(characteristic -> (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) != 0) // filter characteristics that have read property
            .flatMap(connection::readCharacteristic, // read characteristic
                    Pair::new); // merge characteristic with byte[] to keep track from which characteristic the bytes came
}

private Observable<Pair<BluetoothGattCharacteristic, byte[]>> setupNotifications(RxBleConnection connection,
                                                                                List<BluetoothGattCharacteristic> characteristics) {
    return Observable.from(characteristics) // deal with every characteristic separately
            .filter(characteristic -> (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) != 0) // filter characteristics that have notify property
            .flatMap(characteristic -> connection
                            .setupNotification(characteristic) // setup notification for each
                            .flatMap(observable -> observable), // to get the raw bytes from notification
                    Pair::new); // merge characteristic with byte[] to keep track from which characteristic the bytes came
}

除了concatWith()之外,您可以反转顺序并使用startWith().

最好的祝福

转载注明原文:rx-java – 如何以线性方式连接两个可观察的操作(首先执行此操作,然后完成第二个操作)? - 代码日志