使用 RxAndroidBle 编写多个特性的正确方法是什么?
What is the proper way to write multiple characteristics with RxAndroidBle?
我是 Rx 的新手,仍在尝试弄清楚如何正确处理可观察对象。我想知道是否有比使用 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 运算符:
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);
您还可以将可观察对象列表传递给该运算符:
Instead of passing multiple Observables (up to nine) into merge, you
could also pass in a List<> (or other Iterable) of Observables, an
Array of Observables, or even an Observable that emits Observables,
and merge will merge their output into the output of a single
Observable
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.
So I changed my old code to what is above which now uses merge but only one of the characteristics seems to update now.
此行为的原因可能是您使用流的方式:
.subscribe(bytes -> {
Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
((MainActivity)getActivity()).back();
}, BleUtil::logError);
每当发出 bytes
时,您就在调用 Activity.back()
。 .merge()
运算符确实会为执行的每个写入命令发出 bytes
。如果您取消订阅 Subscription
in 即 .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);
}
我是 Rx 的新手,仍在尝试弄清楚如何正确处理可观察对象。我想知道是否有比使用 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 运算符:
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);
您还可以将可观察对象列表传递给该运算符:
Instead of passing multiple Observables (up to nine) into merge, you could also pass in a List<> (or other Iterable) of Observables, an Array of Observables, or even an Observable that emits Observables, and merge will merge their output into the output of a single Observable
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.
So I changed my old code to what is above which now uses merge but only one of the characteristics seems to update now.
此行为的原因可能是您使用流的方式:
.subscribe(bytes -> {
Toast.makeText(getContext(), "Saved Changes", Toast.LENGTH_SHORT).show();
((MainActivity)getActivity()).back();
}, BleUtil::logError);
每当发出 bytes
时,您就在调用 Activity.back()
。 .merge()
运算符确实会为执行的每个写入命令发出 bytes
。如果您取消订阅 Subscription
in 即 .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);
}