在不使用传统监听器的情况下通知链中的错误事件

时间:2016-12-14 19:02:44

标签: rx-java rx-android rxandroidble

我有一个相当复杂的Rx代码链,用于执行许多操作。基本上在启动时,Observable开始发出一个项目列表。对于每个项目,建立连接(这些项目是BLE设备)并写入特征。

此特性每10秒重写一次,直到发生错误(例如拔出电池)。之后,原始列表中的下一个项目将连接到,依此类推。

以下是大部分行动发生的地方:

public Observable<String> connectForPolice(String name, RemovalListener listener) {

        StringBuilder builder = new StringBuilder(mAddress);
        builder.setCharAt(mAddress.length() - 1, '4');
        RxBleDevice device = mRxBleClient.getBleDevice(builder.toString());

        return device.establishConnection(mContext, false)
                .timeout(12, TimeUnit.SECONDS)
                .doOnError(throwable -> {
                    Log.d(TAG, "Error thrown after timeout.");
                    throwable.printStackTrace();
                })
                .flatMap(new Func1<RxBleConnection, Observable<byte[]>>() {
                    @Override
                    public Observable<byte[]> call(RxBleConnection rxBleConnection) {
                        byte[] value = new byte[1];
                        value[0] = (byte) (3 & 0xFF);

                        return Observable // ... we return an observable ...
                                .defer(() -> {
                                    return rxBleConnection.writeCharacteristic(Constants.BUZZER_SELECT, value);
                                })
                                .repeatWhen(observable -> {
                                    return observable.delay(10, TimeUnit.SECONDS);
                                });
                    }
                })
                .observeOn(AndroidSchedulers.mainThread())
                .onErrorResumeNext(throwable -> {
                        throwable.printStackTrace();
                        listener.onFinished(name);
                    return Observable.empty();
                });
    }

这里有一些问题。如您所见,传统的侦听器被传递到此方法中,并且此侦听器在onErrorResumeNext中调用。此侦听器用于从Activity中的RecyclerView中删除该项,但这并不重要。问题是,以这种方式使用侦听器是一种Rx的反模式。以下是相关代码的其余部分,包括调用上述示例的代码:

    @Override
    public void onFinished(String deviceName) {
        mAdapter.removeItem(deviceName);
    }

    private void startConnecting() {
        mIsBeepingAll = true;
        mConnectingSubscription = Observable.from(mAdapter.getItems())
                .flatMap((Func1<Device, Observable<?>>) device -> {
                    Log.d(TAG, "connecting for policing");
                    return device.connectForPolice(device.getName(), PoliceActivity.this);
                }, 1)
                .doOnError(throwable -> throwable.printStackTrace())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<Object>() {
                    @Override
                    public void onCompleted() {
                        Log.d(TAG, "onCompleted...");
                    }

                    @Override
                    public void onError(Throwable e) {
                        e.printStackTrace();
                        Log.d(TAG, "onError...");
                    }

                    @Override
                    public void onNext(Object o) {
                        Log.d(TAG, "onNext... ");
                    }
                });
    }

包含了侦听器的实现。问题是,如何使用Rx执行与侦听器相同的操作?

1 个答案:

答案 0 :(得分:1)

最简单的是改变这个:

            .onErrorResumeNext(throwable -> {
                throwable.printStackTrace();
                listener.onFinished(name);
                return Observable.empty();
            });

进入这个:

            .onErrorResumeNext(throwable -> {
                throwable.printStackTrace();
                return Observable.just(name);
            });

调用者会使用:

private void startConnecting() {
    mIsBeepingAll = true;
    mConnectingSubscription = Observable.from(mAdapter.getItems())
            .flatMap((Func1<Device, Observable<?>>) device -> {
                Log.d(TAG, "connecting for policing");
                return device.connectForPolice(device.getName(), PoliceActivity.this);
            }, 1)
            .doOnError(throwable -> throwable.printStackTrace())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<Object>() {
                @Override
                public void onCompleted() {
                    Log.d(TAG, "onCompleted...");
                }

                @Override
                public void onError(Throwable e) {
                    e.printStackTrace();
                    Log.d(TAG, "onError...");
                }

                @Override
                public void onNext(String deviceName) {
                    Log.d(TAG, "onNext... ");
                    mAdapter.removeItem(deviceName);
                }
            });
}