处置第一个连接后无法重新启动扫描

问题描述

对于我的初始扫描,连接和授权,我有相当长的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.
 */