问题描述
对于我的初始扫描,连接和授权,我有相当长的Rx操作链。这是代码。
fun startScanning() {
getScanObservable()
.take(1)
.map { scanResult ->
rxBleDevice = scanResult.bleDevice
observeDeviceState()
scanResult.bleDevice.establishConnection(false)
}
.flatMap { it }
.map { bleConnection ->
rxBleConnection = bleConnection
bleConnection.discoverServices()
}
.flatMapSingle { it }
.map { services ->
rxBleDeviceServices = services
performAuthentication()
}
.flatMap { it }
.subscribe({
state.postValue(State.AUTHENTICATED)
setupNotifications()
},{
FirebaseCrashlytics.getInstance().recordException(it)
})
.let { disposables.add(it) }
}
因此,总而言之,代码获取第一个扫描结果并立即开始建立连接。完成后,我会发现服务,然后最终对移动客户端进行身份验证。在“链”的末尾(在订阅回调中),我设置了所有需要的特征通知,然后将disposable
保存到我的Compositedisposable
变量中,该变量还包括我所有的disposables从订阅到特征通知。
当我致电disposables.dispose()
时,实际上客户端确实断开了连接。我知道这是因为外围设备显示为断开连接状态,并且RxBleDevice
也显示为disconnected
状态。
问题是,如果我再次调用startScanning
方法,什么也不会发生。永远不会调用第一个map
操作,也不会调用任何订阅方法。仅当我重新启动活动(从头重新实例化所有内容)时,该功能才起作用。
这里还有getScanObservable()
代码:
private fun getScanObservable(): Observable<ScanResult> {
val scanSettings = ScanSettings.Builder()
.setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY)
.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES)
.build()
val scanFilter = ScanFilter.Builder()
.setDeviceName(token.deviceUid)
.build()
return rxBleClient.scanBleDevices(scanSettings,scanFilter)
}
这是我的处置方式:
private val disposables = Compositedisposable()
fun cleanup() {
if (!disposables.isdisposed) {
disposables.dispose()
rxBleDevice = null
rxBleDeviceServices = null
rxBleConnection = null
}
}
每当我想关闭连接并准备重新扫描并重新连接设备时,我都会调用cleanup()
方法。这就是为什么我还要销毁所有RxAndroidBle引用并仅保留RxBleClient引用的原因。
解决方法
之所以无法开始新的扫描,是因为您如何处置前一个。如果您查看实施或Java文档CompositeDisposable.add()
,您会看到:
/** * Adds a disposable to this container or disposes it if the * container has been disposed. * @param disposable the disposable to add,not null * @return true if successful,false if this container has been disposed * @throws NullPointerException if {@code disposable} is null */
您致电CompositeDisposable.dispose()
,因此处理了容器。如果您将.doOnDispose { Log.i("startScanning","disposed!") }
添加到startScanning()
函数中,则会很快发现这一点。
如果要处置CompositeDisposable
的内容而不是容器,请使用CompositeDisposable.clear()
:
/** * Atomically clears the container,then disposes all the previously contained Disposables. */