【问题标题】:Emit an item one at a time, interact with it until a condition is met, then continue for next item一次发出一个项目,与它交互直到满足条件,然后继续下一个项目
【发布时间】:2016-11-17 23:41:52
【问题描述】:

我有一个 BLE 设备列表,并且正在使用 RxJava 与它们进行交互。我需要从列表中发出一个项目,重复写入一个特征直到 X 发生,然后继续到列表中的下一个项目。

当前代码:

Observable.from(mDevices)
                .flatMap(new Func1<Device, Observable<?>>() {
                    @Override
                    public Observable<?> call(Device device) {
                        Log.d(TAG, "connecting for policing");
                        return device.connectForPolicing();
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object o) {
                        Log.d(TAG, "subscribing... ");
                    }
                });

.connectForPolicing() 的样子:

public Observable<byte[]> connectForPolice() {

        ....

        return device.establishConnection(mContext, false)
                .flatMap(new Func1<RxBleConnection, Observable<byte[]>>() {
                    @Override
                    public Observable<byte[]> call(RxBleConnection rxBleConnection) {
                        byte[] value = new byte[1];
                        value[0] = (byte) (3 & 0xFF);
                        //Buzz the device
                        return rxBleConnection.writeCharacteristic(Constants.BUZZER_SELECT, value);
                    }
                })
                .repeat(3)//ignore
                .takeUntil(device.observeConnectionStateChanges().filter(new Func1<RxBleConnection.RxBleConnectionState, Boolean>() {
                    @Override
                    public Boolean call(RxBleConnection.RxBleConnectionState rxBleConnectionState) {

                        return rxBleConnectionState == RxBleConnection.RxBleConnectionState.DISCONNECTING;
                    }
                }));
    }

此代码似乎会立即发出列表中的所有项目,因此会同时连接和蜂鸣所有项目。如何一次发出一个项目以便与它们交互?

伪代码类似于:

for(Device device : devices) {
    device.connect();
    while(device.isConnected()) {
        device.beep();
    }
}

【问题讨论】:

    标签: android rx-java rx-android android-ble rxandroidble


    【解决方案1】:

    flatMap 替换为concatMap

    .concatMap(device -> device.connectForPolicing())
    

    flatMap 使用 merge 运算符。它立即发出所有项目。虽然concatMap 使用concat,但它会按顺序发出项目。 Good article about it.

    【讨论】:

    • 我阅读了这篇文章。据我了解.concatMap() 只是保留了项目的顺序,但将我的.flatMap() 切换为.concatMap() 不会导致我正在寻找的阻塞行为。如果两个项目在列表中,它们将被我一个接一个地发出。
    • 会的,但是每个项目都会等到 device.connectForPolicing() for pervious item 完成。
    • 我已经尝试了您的建议,但尚未能够获得原始问题中描述的功能。最多,我可以让一个设备发出哔哔声,但不会重复。看着我的日志,似乎只有 1 项正在通过。
    【解决方案2】:

    您可以使用.flatMap(Observable, int) 运算符。

    Observable.from(mDevices)
                .flatMap(
                    new Func1<Device, Observable<?>>() {
                        @Override
                        public Observable<?> call(Device device) {
                            Log.d(TAG, "connecting for policing");
                            return device.connectForPolicing();
                        }
                    },
                    1
                )
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Action1<Object>() {
                    @Override
                    public void call(Object o) {
                        Log.d(TAG, "subscribing... ");
                    }
                });
    

    int 参数限制了最大并发操作。在这种情况下,它将按顺序处理。

    如果您想反复发出蜂鸣声直到设备断开连接,则还需要更改 connectForPolice() 函数:

    public Observable<byte[]> connectForPolice(RxBleDevice device) {
    
        ....
    
        return device.establishConnection(mContext, false)
                .flatMap(new Func1<RxBleConnection, Observable<byte[]>>() { // once the connection is established ...
                    @Override
                    public Observable<byte[]> call(RxBleConnection rxBleConnection) {
                        byte[] value = new byte[1];
                        value[0] = (byte) (3 & 0xFF);
                        //Buzz the device
                        return Observable // ... we return an observable ...
                                .defer(new Func0<Observable<byte[]>>() {
                                    @Override
                                    public Observable<byte[]> call() {
                                        return rxBleConnection.writeCharacteristic(Constants.BUZZER_SELECT, value); // ... (that on each subscription will emit a fresh write characteristic observable) ...
                                    }
                                })
                                .repeatWhen(new Func1<Observable<? extends Void>, Observable<?>>() { // ... which we will subscribe (the Observable.defer()) again ...
                                    @Override
                                    public Observable<?> call(Observable<? extends Void> observable) {
                                        return observable.delay(10, TimeUnit.SECONDS); // ... after 10 seconds from the previous complete
                                    }
                                });
                    }
                })
                .onErrorResumeNext(new Func1<Throwable, Observable<? extends byte[]>>() { // if the device will trigger disconnect then a BleDisconnectedException will be thrown ...
                    @Override
                    public Observable<? extends byte[]> call(Throwable throwable) {
                        return Observable.empty(); // ... in which situation we will just finish the Observable
                    }
                });
    }
    

    【讨论】:

    • 我认为主要问题是在.connectForPolicing() 方法中,.establishConnection().writeCharacteristic() 方法是异步的。我需要重复写入特征,直到 X 发生,此时可以允许下一个项目顺流而下。
    • 是的,虽然我只看到一个项目在流中发出,即使列表包含 > 1 个项目,因此只有 1 个项目发出哔哔声。
    • 您希望何时断开与设备的连接?
    • 首先我需要弄清楚如何反复发出哔哔声,但是当抛出特定异常时需要发出列表中的下一项。
    • 你的意思是尽可能快地重复,或者每秒响一次就足够了?问题在于connectForPolicing() 函数。我认为您可能误用了.repeat() 运算符。
    猜你喜欢
    • 1970-01-01
    • 2018-04-20
    • 2021-02-22
    • 1970-01-01
    • 2021-07-09
    • 2021-11-26
    • 2019-02-27
    • 1970-01-01
    • 2023-03-29
    相关资源
    最近更新 更多