RXAndroid 编写嵌套订阅的更好方法
RXAndroid better way to write nested subscriptions
我正在为 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!!!!! */
}
本质上,我有一系列函数对一个事物执行一个动作,然后订阅生成的 Single(我想我使用的术语是正确的)
我的问题是,什么是更好的写法?
更重要的是,我从未取消订阅的嵌套订阅会怎样?请注意,在第一个函数中,我调用了一个 take(1)...最终我只是处理了调用所有这些的顶级一次性。
没有。那不是 RX 方式。我建议给 this a quick read.
tl;dr 是您希望对代码进行布局,使其像溪流一样流动。 Rx 试图解决的其中一件事是消除嵌套回调。这种 "stream" 方法可以做到这一点。
现在谈谈您可以做些什么来让它变得更好。这是一种重写代码的方法,它是一个流而不是一组嵌套的回调:
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 */)
}
这是另一种方法:
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 */)
}
我正在为 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!!!!! */
}
本质上,我有一系列函数对一个事物执行一个动作,然后订阅生成的 Single(我想我使用的术语是正确的)
我的问题是,什么是更好的写法?
更重要的是,我从未取消订阅的嵌套订阅会怎样?请注意,在第一个函数中,我调用了一个 take(1)...最终我只是处理了调用所有这些的顶级一次性。
没有。那不是 RX 方式。我建议给 this a quick read.
tl;dr 是您希望对代码进行布局,使其像溪流一样流动。 Rx 试图解决的其中一件事是消除嵌套回调。这种 "stream" 方法可以做到这一点。
现在谈谈您可以做些什么来让它变得更好。这是一种重写代码的方法,它是一个流而不是一组嵌套的回调:
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 */)
}
这是另一种方法:
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 */)
}