错误状态:使用 IOWebSocketChannel 时已监听 Stream

Posted

技术标签:

【中文标题】错误状态:使用 IOWebSocketChannel 时已监听 Stream【英文标题】:Bad state: Stream has already been listened to when using IOWebSocketChannel 【发布时间】:2021-03-30 01:49:27 【问题描述】:

我有一个 StreamBuilder,它监听使用包 web_socket_channel: ^1.1.0 创建的流。

Stream getLocationsStream(LatLngBounds latLngBounds, LatLng location) 
  if (branchMapChannel == null)
    branchMapChannel = IOWebSocketChannel.connect(wsEndpointURL("business/branch/maps"));
  return branchMapChannel.stream;

StreamBuilder 监听这个流(getLocationsStream())。我在名为 Maps() 的自定义小部件中使用此 Streambuilder。在主页中调用 Maps() 时,它可以正常工作。但是当 Maps() 在另一个页面上被调用时,它会显示以下错误。

错误状态:Stream 已被监听。

当异常被抛出时,这是堆栈: 我/颤振(2977):#3 _CompleterStream.listen 包:async/src/stream_completer.dart:135 我/颤振(2977):#7 _StreamBuilderBaseState._subscribe 包:flutter/…/widgets/async.dart:137 我/颤振(2977):#8 _StreamBuilderBaseState.initState 包:flutter/…/widgets/async.dart:111 我/颤振(2977):#9 StatefulElement._firstBuild 包:flutter/…/widgets/framework.dart:4812 我/颤振(2977):#10 ComponentElement.mount 包:flutter/…/widgets/framework.dart:4649 我/颤振(2977):#11 Element.inflateWidget 包:flutter/…/widgets/framework.dart:3615 我/颤振(2977):#12 Element.updateChild 包:flutter/…/widgets/framework.dart:3377 我/颤振(2977):#13 ComponentElement.performRebuild 包:flutter/…/widgets/framework.dart:4700

【问题讨论】:

【参考方案1】:

出现问题是因为您尝试订阅 Single Subscription Stream 两次。

如果你查看IOWebSocketChannel的文档,你可以看到:

流 → 流 从另一个端点发出值的单订阅流。 最终

建议 #1:

而不是直接将套接字流分配给流生成器:

创建一个 Socket Utility 类(一个 Singleton 或使用依赖注入来传递对象) 在 Socket Utility 类中监听套接字事件 在您的 Socket Utility 中提供添加侦听器的选项 每当流发生变化时,通知所有监听器 在您的 Maps 类中使用 Socket Utility 对象并设置侦听器/回调

建议 #2:

只需使用asBroadcastStream 将您的流转换为广播流。

Stream getLocationsStream(LatLngBounds latLngBounds, LatLng location) 
  if (branchMapChannel == null) 
    branchMapChannel = IOWebSocketChannel.connect(wsEndpointURL("business/branch/maps"));
    broadCastStream = branchMapChannel.stream.asBroadcastStream();
  
  return broadCastStream;

【讨论】:

@ChristopherMoore 是的,正在寻找文档。我总是喜欢第一种方式,所以先写了,然后添加 asBroadCastStream 作为第二个选项;) 你能分享第一个选项的代码吗?第二个选项不起作用 @AbhijithK 您是将流存储在变量中还是只是将其返回:return branchMapChannel.stream.asBroadcastStream();?对于第一个,我已经提到了那里的步骤,如果您需要代码,我必须为您编写一个完整的类。 我尝试将其作为广播流返回,但错误仍然存​​在。让我试试第一个选项。 不,我的意思是如果你像这样返回它:return branchMapChannel.stream.asBroadcastStream(); 错误就会出现。您必须将branchMapChannel.stream.asBroadcastStream(); 的值存储在一个变量中并返回该变量。如我的回答所示,broadCastStream 是一个与 branchMapChannel 范围相同的变量

以上是关于错误状态:使用 IOWebSocketChannel 时已监听 Stream的主要内容,如果未能解决你的问题,请参考以下文章

BigQuery 插入错误,状态:挂起,状态码 5

使用空 SQL 状态获取错误代码 4220

React Native - 使用状态显示/隐藏错误消息

服务器错误状态码

Boost statechart - 使用状态图作为模板参数时的编译错误

如何使用 LiveData 处理错误状态?