RXAndroid是编写嵌套订阅的更好方法

RXAndroid是编写嵌套订阅的更好方法,android,android-bluetooth,rx-android,rxandroidble,Android,Android Bluetooth,Rx Android,Rxandroidble,我正在使用Android的RXBle库。为了从BLE外围设备(BLE设备)读取数据,我设置了大量的订阅,所有订阅都在彼此内部,如下所示: Disposable scanSubscription = null; public void startScan() { scanSubscription = rxBleClient .scanBleDevices(settings, filter) .take(1)

我正在使用Android的RXBle库。为了从BLE外围设备(BLE设备)读取数据,我设置了大量的订阅,所有订阅都在彼此内部,如下所示:

    Disposable scanSubscription = null;

    public void startScan() {
        scanSubscription = rxBleClient
            .scanBleDevices(settings, filter)
            .take(1)
            .subscribe(
                scanResult -> connectDevice(scanResult.getBleDevice()),
                throwable -> {}
            );
    }

    public void connectDevice(RxBleDevice device) {
        device
            .establishConnection(false)
            .subscribe(
                connection -> requestMtu(connection),
                throwable -> {}
            );
    }

    public void requestMtu(final RxBleConnection connection) {
        connection
            .requestMtu(185)
            .subscribe(
                mtu -> readCharacteristic(connection),
                throwable -> {}
            );
    }

    public void readCharacteristic(final RxBleConnection connection) {
        /* this one eventually scanSubscription.dispose!!!!! */
    }
从本质上说,我有一系列函数,这些函数对一件事情执行一个操作,然后订阅结果单(我认为我正确地使用了术语)

我的问题是,写这篇文章的更好方法是什么


更重要的是,我从未取消订阅的嵌套订阅发生了什么?请注意,在第一个函数中,我调用了take(1)…最终我只处理调用所有这些的顶级一次性文件。

否。这不是RX方式。我建议给予

tl;dr是指您希望对代码进行布局,使其像流一样流动。Rx试图解决的问题之一是消除嵌套回调。这种“流”方法可以做到这一点

现在来看看你能做些什么让它变得更好。以下是一种重写代码的方法,使其成为一个流而不是一组嵌套回调:

Disposable scanSubscription = null;

public void doThing() {
    scanSubscription = rxBleClient
        .scanBleDevices(settings, filter)
        .take(1)
        .map(scanResult -> scanResult.establishConnection(false))
        .map(connection -> connection.requestMtu(185))
        .map(mtu -> <do thing>)
        .subscribe(/* do things with final value */)
}

@idunnoloz感谢您的回复。我有点困惑的是,我如何从代码中你说的“做事”部分访问
连接。有什么建议吗?一旦MTU发生更改,我需要从连接中读取。@wheresmycookie取决于您想要的“干净程度”,您可以让
map()
返回一对,如下所示:
.map(connection->new pair(connection,connection.requestMtu(185))
。或者,您可以创建一个结果类,其中包含要传递到流中的字段,并返回该字段。@wheresmycookie我更新了我的答案,为您提供了另一种方法,如果您需要传递流中的连接,您可以解决此问题。啊,太好了!这就是我要找的!还有一件事,我很乐意改进这个解决方案:假设每隔几分钟我就想调用
doThing()
,在您的示例中,这将删除当前订阅并用新版本的订阅“替换”它。(我知道这是一个奇怪的请求,但由于操作系统的限制,我不得不偶尔重置扫描)。只需在延迟循环中调用
dispose()
然后再次调用
doThing()
就足够了吗?@wheresmycookie取决于此
dispose()
将为流中运行的所有线程设置中断标志,因此您需要确保代码能够正确处理中断和错误。但是假设你能优雅地处理中断,那么是的,你可以这么做。您不需要使用“延迟循环”来执行此操作,除非您需要确保执行已停止。一旦调用
dispose()
,您的消费者将停止接收结果。
Disposable scanSubscription = null;

public void doThing() {
    scanSubscription = rxBleClient
        .scanBleDevices(settings, filter)
        .take(1)
        .flatMap(scanResult -> scanResult.establishConnection(false))
        .flatMap(connection -> connection.requestMtu(185).map(result -> Pair(connection, result)))
        .flatMap(result -> {
            Connection c = result.first;
            Mtu mtu = result.second;
            //do thing
        })
        .subscribe(/* do things with final value */)
}