如何使用RxAndroidBle在Android中执行阻止写入操作。仅当写入操作成功时,才应执行下一条命令。
protected void doWriteBytes(UUID characteristic, byte[] bytes) {
final Disposable disposable = connectionObservable
.flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(characteristic, bytes))
.observeOn(AndroidSchedulers.mainThread())
.retry(BT_RETRY_TIMES_ON_ERROR)
.subscribe(
value -> {
Timber.d("Write characteristic %s: %s",
BluetoothGattUuid.prettyPrint(characteristic),
byteInHex(value));
},
throwable -> onError(throwable)
);
compositeDisposable.add(disposable);
}
protected void test() {
// blocking write bytes
doWriteBytes(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x35, 0x12});
// following command should be only performed if doWriteBytes is successful executed
foo();
// blocking write bytes
doWriteBytes(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x5, 0x6, 0x1});
bar();
}
我知道订阅和onComplete,但是也可以不用这些方法吗?
背景是我想在几个不同的子类中覆盖测试方法,因此我可以执行各种doWriteBytes命令(例如ACK命令)以向蓝牙设备发送一些字节,但是我需要确保下一个命令是仅在ACK命令成功发送后才执行。
也许这更多是一个RxJava2问题,但我对此并不十分熟悉。
编辑:
感谢您的回答@Dariusz Seweryn。抱歉,我的问题可能不太清楚。我会尽量具体化。
我想像在test()中编写普通函数一样编写源代码,以抽象化RxJava2实现。唯一的不同是,应该通过RxAndroidBle完成doWriteBytes和其他蓝牙操作(通知,读取)。 我必须写给蓝牙设备的内容取决于通知字节或test()方法中的其他算法。另外,我想覆盖test()方法以为完全不同的蓝牙设备实现不同的蓝牙通信流程。顺序处理蓝牙操作始终很重要。
现在我想到了三个想法:
1)我的第一个想法是实现所有RxAndroidBle操作阻止,因此我可以将simple用于循环。
2)我的第二个想法是在运行时观察中动态地添加(concat?)到test()方法中的另一个,该方法是顺序处理的,但我总是需要以前观察中的返回值?
3)我的第三个想法是将写/通知/写操作作为一种方法组合在一起,可以在test()方法中调用它。该操作应将字节写入特征A,然后等待有关特征B的通知,对接收到的字节进行一些处理,然后再次写入特征C。 但是在添加的test()方法中,编写了什么内容或在运行期间如何动态地进行通知过程。
对于RxJava2中的问题,也许有一个优雅的解决方案,或者根本不可能?
编辑2:
我尝试实现所有这三个想法,但不幸的是我没有成功。
1)
connectionObservable
.flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(characteristic, bytes))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(BT_RETRY_TIMES_ON_ERROR)
.blockingSubscribe(
value -> {
Timber.d("Write characteristic %s: %s",
BluetoothGattUuid.prettyPrint(characteristic),
byteInHex(value));
processBtQueue();
},
throwable -> onError(throwable)
);
即使成功,它总是会阻塞吗?我必须在某个地方释放它吗?另外,该方法返回void并且不再是一次性的,但是我无法处理它。
2)我正在为这个想法而苦苦挣扎。如果我不知道起始的可观察物,我应该关注哪个可观察物? connectionObserable不起作用,因为它包含RxBleConnection。第二个问题是,蓝牙操作后的值就是Java对象类!我是否每次都要投射?您是否有示例如何将蓝牙写入操作与通知蓝牙结果进行连接?
3)这个想法的问题是,我不知道如何在运行时动态地将处理部分动态添加到RxJava订阅部分之外的通知中?
我对第3号想法有一个可行的解决方案
protected Observable<byte[]> doWriteNotify(UUID characteristic, byte[] bytes, Observable<byte[]> notificationObservable) {
Observable observable = connectionObservable
.flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(characteristic, bytes))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(BT_RETRY_TIMES_ON_ERROR)
.flatMap( writeBytes -> notificationObservable)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.retry(BT_RETRY_TIMES_ON_ERROR);
compositeDisposable.add(observable.subscribe());
return observable;
}
顺便说一句。这些问题我应该在stackoverflow上创建单独的线程吗?
如果有帮助,您可以找到我的实验源代码here。
答案 0 :(得分:0)
我知道订阅和onComplete,但是也可以不用这些方法吗?
给出:
Completable foo() { ... }
Completable bar() { ... )
一个人可以做:
Disposable testDisposable = connectionObservable
.flatMapCompletable(connection ->
connection.writeCharacteristic(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x35, 0x12}).ignoreElement()
.andThen(foo())
.andThen(connection.writeCharacteristic(UUID.fromString("f433bd80-75b8-11e2-97d9-0002a5d5c51b"), new byte[] {0x5, 0x6, 0x1}).ignoreElement())
.andThen(bar())
)
.subscribe(
() -> { /* completed */ },
throwable -> { /* error happened */ }
)
使用.subscribe()
结束以上内容可以控制流完成多少个连接。在上面的示例中,如果连接在第一次写入过程中过早终止,则所有后续操作(foo()
,写入,bar()
)将根本不会发生。
编辑:
您所有的想法都可能有效-您可以尝试一下。
对于RxJava2中的问题,也许有一个优雅的解决方案,或者根本不可能?
如果确实需要.blocking*()
/ Observable
/ Single
类,则有Completable
个函数。不过请小心-由于您的应用程序引入了更多状态,因此您可能会开始遇到一些难以调试的问题,具体取决于您的实现。