首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >produce<Type>诉Channel<Type>()

produce<Type>诉Channel<Type>()
EN

Stack Overflow用户
提问于 2019-05-22 13:27:40
回答 1查看 357关注 0票数 0

试着理解频道。我想要引导安卓BluetoothLeScanner。为什么这样做:

代码语言:javascript
复制
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
}

但不是这个:

代码语言:javascript
复制
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:,根据docs:The channel is closed when the coroutine completes.,这是有意义的。我知道我们可以将suspendCoroutineresume一起用于一次callback-replacement。然而,这是一个侦听器/流-情况。我不想让协同线完成

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-05-23 21:10:26

使用produce,您可以将范围引入您的频道。这意味着,生成在通道上流的项的代码可以被取消。

这也意味着您的通道的生存期从produce的lambda开始,到此lambda结束时结束。

在您的示例中,produce调用的lambda几乎立即结束,这意味着您的通道几乎立即关闭。

将代码更改为如下内容:

代码语言:javascript
复制
fun CoroutineScope.startScan(filters: List<ScanFilter>, settings: ScanSettings = defaultSettings): ReceiveChannel<ScanResult?> = produce {
    scanCallback = object : ScanCallback() {
        override fun onScanResult(callbackType: Int, result: ScanResult) {
            offer(result)
        }
    }
    scanner.startScan(filters, settings, scanCallback)

    // now suspend this lambda forever (until its scope is canceled)
    suspendCancellableCoroutine<Nothing> { cont ->
        cont.invokeOnCancellation {
            scanner.stopScan(...)
        }
    }
}

...
val channel = scope.startScan(filter)
...
...
scope.cancel() // cancels the channel and stops the scanner.

我添加了行suspendCancellableCoroutine<Nothing> { ... },使其挂起“永远”。

更新:使用produce并以结构化方式处理错误(允许结构化并发):

代码语言:javascript
复制
fun CoroutineScope.startScan(filters: List<ScanFilter>, settings: ScanSettings = defaultSettings): ReceiveChannel<ScanResult?> = produce {
    // Suspend this lambda forever (until its scope is canceled)
    suspendCancellableCoroutine<Nothing> { cont ->
        val scanCallback = object : ScanCallback() {
            override fun onScanResult(callbackType: Int, result: ScanResult) {
                offer(result)
            }
            override fun onScanFailed(errorCode: Int) {
                cont.resumeWithException(MyScanException(errorCode))
            }
        }
        scanner.startScan(filters, settings, scanCallback)

        cont.invokeOnCancellation {
            scanner.stopScan(...)
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56257990

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档