经过一定时间后关闭流

问题描述

我正在尝试创建一个流程,该流程将发布发现蓝牙LE设备的结果。

扫描此类设备时,永远不会收到完成的扫描信号,因此我必须在一定时间后手动停止流量。

我目前用于实现上述目的的代码如下:

({mockScan用于在模拟器上工作时模拟扫描,当我移至真实设备时,它将被普通扫描取代)

在我的视图模型上:

private fun startScanning() {
        scanJob?.cancel() //cancel the scanning job if there is any
        _devices.clear() //clear the currently discovered devices
        scanJob = launch { //launch a new job
            repo.startScanning(10000) //this will call the repo,it creates a flow with the results
                .flowOn(dispatcher.IO) 
                .buffer()
                .onCompletion {
                    scanJob = null
                    updateState() //this will update the screen state
                }
                .catch {
                    Timber.d("Error ${it.message}") //for Now I just show the error,later I will handle it
                }
                .collect { //when a new entry comes
                    _devices.add(it) //I add it to my existing devices
                    devices.postValue(_devices) //and post the value to my live data which will be picked up by the adapter
                }
        }
        updateState() //this will update the screen state
    }

以及在我的存储库中

    @ExperimentalCoroutinesApi
    override fun startScanning(period: Long): Flow<Device> =
        callbackFlow {
            //this is a dummy interface I created to test scanning
            val callback = object : LeScanCallback { 
                override fun onScanResult(callbackType: Int,result: ScanResult?) {
                    offer(Device(result!!.device.first!!,result.device.second!!))
                }
            }
            mockScan(callback) //this simulates scanning
            val scope = this 
            launch {
                delay(period) //after some time cancel the scope (which should call awaitClose)
                scope.cancel()
            }
            awaitClose {
                //here I will put the code that will actually stop the scan from the adapter
                Timber.d("Finished")
            }
        }

为完成起见,这是mockScan方法

private fun mockScan(callback: LeScanCallback) {
    launch {
        launch(dispatcherImpl.IO) {
            var id = 0
            scanning = true
            while (scanning) {
                id++
                delay(Random.nextInt(1,3) * 1000L)
                val device = Pair("address $id","name $id")
                callback.onScanResult(3,ScanResult(device))
            }

        }
    }
}

上述情况似乎可行,并且确实在10秒钟后调用onCompletion函数,以便我可以清理所有需要的东西

我的问题是,是否有更好的方法来限制流可以运行的时间?还是我使用启动->延迟-> scope.close()方法卡住了?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)