Kotlin Channel轮询异常:发送的Item未全部被receive接收
Kotlin Channel轮询丢失Item问题排查
你的问题核心出在Channel的迭代逻辑和手动receive()重复调用上,导致一半的Item被无声丢弃,具体分析如下:
问题原因
for (element in basketChannel) 这个循环本身就是Kotlin Channel提供的迭代式接收语法——每次循环迭代时,底层会自动调用receive()从Channel取出一个元素并赋值给element。而你在循环体内又额外调用了一次basketChannel.receive(),这就意味着:
- 第一次循环:取出Item1(通过迭代)打印,然后又取出Item2(手动
receive)但没处理,直接丢弃 - 第二次循环:取出Item3(迭代)打印,然后取出Item4(手动
receive)丢弃
最终只打印了Item1和Item3,Item2、Item4被无意义的receive()消耗却没输出。
修复方案
只需要保留一种接收方式即可,两种可选:
方案1:保留for-in迭代(推荐,更简洁)
删掉循环内多余的receive():
fun startPolling() { viewModelScope.launch { Log.e(TAG, "Starting Polling") for (element in basketChannel) { logE("basketChannel Item poll -> $element") // 移除多余的basketChannel.receive() } } }
方案2:手动循环调用receive()
如果想显式用poll/receive的方式,改用while循环:
fun startPolling() { viewModelScope.launch { Log.e(TAG, "Starting Polling") while (true) { val element = basketChannel.receive() logE("basketChannel Item poll -> $element") } } }
额外说明
- Channel的
for-in迭代会自动处理Channel的关闭逻辑:当Channel被关闭且缓冲区为空时,循环会自动终止 - 手动
receive()在Channel关闭后会抛出ClosedReceiveChannelException,如果需要处理关闭,可以用receiveCatching()替代
内容的提问来源于stack exchange,提问作者Compose Learner
相关产品推荐
相关产品推荐

