【发布时间】:2019-10-09 00:15:57
【问题描述】:
试图了解渠道。我想对 android BluetoothLeScanner 进行通道化。为什么会这样:
fun startScan(filters: List<ScanFilter>, settings: ScanSettings = defaultSettings): ReceiveChannel<ScanResult?> {
val channel = Channel<ScanResult>()
scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
channel.offer(result)
}
}
scanner.startScan(filters, settings, scanCallback)
return channel
}
但不是这个:
fun startScan(scope: CoroutineScope, filters: List<ScanFilter>, settings: ScanSettings = defaultSettings): ReceiveChannel<ScanResult?> = scope.produce {
scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
offer(result)
}
}
scanner.startScan(filters, settings, scanCallback)
}
它告诉我Channel was closed 第一次想呼叫offer。
EDIT1: 根据文档:The channel is closed when the coroutine completes. 这是有道理的。我知道我们可以使用suspendCoroutine 和resume 一次性使用callback-replacement。然而,这是一个监听器/流的情况。我不希望协程完成
【问题讨论】:
-
确保您的协程范围的生命周期与蓝牙扫描仪的范围相匹配。如果您有一个活动绑定范围但不适合,请创建一个不同的范围。
-
我玩过瞄准镜,没什么区别。我想问题是在scanner.startscan之后产生返回,这意味着它已经完成了
-
produce调用立即返回,它返回的值是您需要从中消费数据的ReceiveChannel。但是,是的,produce块应该是一个无限循环,将数据推送到通道中。在您的情况下,produce块立即完成。所以你的第一个例子更适合你的基于回调的方法。 -
produce在这种情况下不是您想要的。对于这样的用例,您需要一个合适的渠道。
标签: kotlin coroutine kotlin-coroutines kotlinx.coroutines.channels