使用RxAndroidBle编写多个特征的正确方法是什么?

时间:2017-09-25 18:01:21

标签: android rx-android rxandroidble

我是Rx的新手,仍在努力弄清楚如何正确处理observable。我想知道是否有更好的方法来编写多个特征,而不是一次使用RxAndroidBle做一个?目前我正在使用下面的代码一次做一个。

Observable<RxBleConnection> mConnectionObservable;

private void saveChanges(String serialNumber, Date date, MachineTypeEnum machineType, MachineConfig machineConfig) {
    mWriteSubscription = mConnectionObservable
            .flatMap(rxBleConnection -> Observable.merge(
                    getWrites(rxBleConnection, serialNumber, machineType, machineConfig, date)
            ))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(bytes -> {
                Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
                ((MainActivity)getActivity()).back();
            }, BleUtil::logError);
}

private Iterable<? extends Observable<? extends byte[]>> getWrites(RxBleConnection rxBleConnection,
                                                                   String serialNumber,
                                                                   MachineTypeEnum machineType,
                                                                   MachineConfig machineConfig,
                                                                   Date date) {
    List<Observable<byte[]>> observables = new ArrayList<>();


    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_WRITE_SERIAL_NUMBER,
            Utf8Util.nullPad(serialNumber, 16).getBytes()).doOnError(throwable -> Log.e("Write", "serial failed", throwable)));

    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_MACHINE_TYPE,
            new byte[]{(byte) machineType.val()}).doOnError(throwable -> Log.e("Write", "machine type failed", throwable)));

    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_CHARACTERISTIC,
            MachineConfigBitLogic.toBytes(machineConfig)).doOnError(throwable -> Log.e("Write", "machine config failed", throwable)));

    observables.add(rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.CurrentTime.Characteristics.UUID_CURRENT_TIME,
            TimeBitLogic.bytesFor(date)).doOnError(throwable -> Log.e("Write", "date failed", throwable)));

    return observables;
}

所以我将旧代码更改为上面现在使用merge的内容,但现在只有一个特性似乎更新。

2 个答案:

答案 0 :(得分:2)

我会使用merge运算符:

mConnectionObservable
        .flatMap(rxBleConnection -> 
        Observable.merge(
        rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DeviceInformation.Characteristics.UUID_SERIAL_NUMBER,
            Utf8Util.nullPad(serialNumber, 16).getBytes()
        ),
        rxBleConnection.writeCharacteristic(
            Constants.Bluetooth.Services.DrainCleaner.Characteristics.UUID_MACHINE_TYPE,
            new byte[]{(byte) machineType.val()}
        ))
        .subscribe(bytes -> {/* do something*/}, BleUtil::logError);

您也可以将一个observable列表传递给该运算符:

  

不是将多个Observable(最多九个)传递给合并,而是   也可以传入List&lt;&gt; (或其他可迭代的)Observables,a   Observables数组,甚至是发出Observables的Observable,   并合并将其输出合并为单个输出   可观察到的

答案 1 :(得分:1)

RxAndroidBle库正在序列化任何BLE请求,因为Android上的BLE实现主要是同步的(尽管Android vanilla API表明它不是)。

虽然您需要了解合并运算符的作用,但合并写入是一种很好的方法:

 * You can combine the items emitted by multiple Observables so that they appear as a single Observable, by
 * using the {@code merge} method.
  

所以我将旧代码更改为上面现在使用merge的内容,但现在只有一个特性似乎更新。

此行为的原因可能是您使用流的方式:

        .subscribe(bytes -> {
            Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
            ((MainActivity)getActivity()).back();
        }, BleUtil::logError);

每当发出bytes时,您都在调用Activity.back().merge()运算符会为每个执行的写命令发出bytes。如果您取消订阅Subscription中的.onPause(),则在第一次写入完成后立即取消订阅。 您可以让您的流程等到所有写入完成后如下:

private void saveChanges(String serialNumber, Date date, MachineTypeEnum machineType, MachineConfig machineConfig) {
    mWriteSubscription = mConnectionObservable
        .flatMap(rxBleConnection -> 
            Observable.merge(
                getWrites(rxBleConnection, serialNumber, machineType, machineConfig, date)
            )
            .toCompletable() // we are only interested in the merged writes completion
            .andThen(Observable.just(new byte[0])) // once the merged writes complete we send a single value that will be reacted upon (ignored) in .subscribe()
        )
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(ignored -> {
            Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
            ((MainActivity)getActivity()).back();
        }, BleUtil::logError);
}