stream_channel/MultiChannel..VirtualChannel..sink.add(msg) 在使用带有类型的消息(例如 )时会抛出异常

移动开发 2026-07-09

我正在按照API文档中最新版本(2.1.4)的示例代码进行学习,链接中的示例为 示例代码。我的 async 版本是2.13.1(截至目前也是最新版本)。

具体来说,我正在创建一个 MultiChannel.VirtualChannel,从一个 StreamChannelController 开始,其中通过泛型表示法显式声明为特定类型的消息被 sink 标记(例如 String)。但它抛出了这个异常:type 'List<Object?>' is not a subtype of type 'String' of 'data'

这段非常简单的代码:

import 'package:stream_channel/stream_channel.dart';

void main() {
  var dummyCtrl1 = StreamChannelController<String>();
  var multiChannel = MultiChannel<String>(dummyCtrl1.local);
  var channel1 = multiChannel.virtualChannel();
  channel1.sink.add("AAA");
}

抛出以下异常:

type 'List<Object?>' is not a subtype of type 'String' of 'data'
#0      _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:118:14)
#1      _MultiChannel.virtualChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:212:35)
#2      _RootZone.runUnaryGuarded (dart:async/zone.dart:1778:10)
#3      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:381:11)
#4      _BufferingStreamSubscription._add (dart:async/stream_impl.dart:312:7)
#5      _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:798:19)
#6      _StreamController._add (dart:async/stream_controller.dart:663:7)
#7      _StreamController.add (dart:async/stream_controller.dart:618:5)
#8      _RootZone.runUnaryGuarded (dart:async/zone.dart:1778:10)
#9      _BufferingStreamSubscription._sendData (dart:async/stream_impl.dart:381:11)
#10     _BufferingStreamSubscription._add (dart:async/stream_impl.dart:312:7)
#11     _SyncStreamControllerDispatch._sendData (dart:async/stream_controller.dart:798:19)
#12     _StreamController._add (dart:async/stream_controller.dart:663:7)
#13     _StreamController.add (dart:async/stream_controller.dart:618:5)
#14     _StreamSinkWrapper.add (dart:async/stream_controller.dart:898:13)
#15     _GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:125:12)
#16     main (file:///.../fails.dart:8:17)
#17     _delayEntrypointInvocation.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:314:19)
#18     _RawReceivePort._handleMessage (dart:isolate-patch/isolate_patch.dart:193:12)

但如果完全移除 <String> 或改为 <dynamic>,就不会抛出异常。

_GuaranteeSink.add (package:stream_channel/src/guarantee_channel.dart:118:14) 是:

  @override
/*118*/  void add(T data) {
    if (_closed) throw StateError('Cannot add event after closing.');
    if (_inAddStream) {
      throw StateError('Cannot add event while adding stream.');
    }
    if (_disconnected) return;

    _inner.add(data);
  }

_MultiChannel.virtualChannel.<anonymous closure> (package:stream_channel/src/multi_channel.dart:212:35) 是:

    controller.local.stream.listen(
/*212*/        (message) => _inner!.sink.add(<Object?>[outputId, message]),
        onDone: () => _closeChannel(inputId, outputId));
    return VirtualChannel._(
        this, outputId, controller.foreign.stream, controller.foreign.sink);
  }

一个错误报告已经提交(至今尚无回应)。

是否只有移除/放宽消息类型才是解决办法?(我的实际用例是使用我自己的消息类,可以安全地简化为一个Map。)

解决方案

这之所以会这样,是因为在解码JSON时——尤其是在 dart2wasm / WebAssembly场景下——数组中的数值在运行时可能会返回为 double,而不是 int

内部,MultiChannel 期望通道ID是一个 int,并执行如下的类型转换:

final id = msg[0] as int;

如果解码后的值实际上是一个 double(例如 1.0),则类型转换失败,错误为:

type 'double' is not a subtype of type 'int'

修复

在转换为 int 之前,先经过 num 的强制转换:

final id = (msg[0] as num).toInt();

这可同时正确处理 intdouble

额外信息

这似乎是 stream_channel 中的一个已知问题。

升级该包可能会解决它:

dependencies:
  stream_channel: ^2.1.2
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章