diff --git a/client/lib/bridge/vpn_bridge.dart b/client/lib/bridge/vpn_bridge.dart index 480c588..804fbe8 100644 --- a/client/lib/bridge/vpn_bridge.dart +++ b/client/lib/bridge/vpn_bridge.dart @@ -223,18 +223,28 @@ class VpnNativeBridge implements VpnBridge { Future setKillSwitch({required bool on}) => _method.invokeMethod('setKillSwitch', on); - @override - Stream get statusStream => _statusRaw + // ⚠️ EventChannel 原生侧只保留「一个」sink:每次 receiveBroadcastStream() + listen 都会 + // 触发 onListen 覆盖原生 sink → 多个订阅者(连接页速度 + ConnectionController 回写延迟) + // 互相抢,后订阅的赢、先订阅的流变哑。必须只调一次 receiveBroadcastStream()、缓存成共享 + // 广播流,所有 Dart 订阅者复用同一条原生订阅。 + late final Stream _statusStream = _statusRaw .receiveBroadcastStream() - .map((e) => VpnStatus.fromString(e?.toString() ?? 'error')); + .map((e) => VpnStatus.fromString(e?.toString() ?? 'error')) + .asBroadcastStream(); - @override - Stream get statsStream => _statsRaw + late final Stream _statsStream = _statsRaw .receiveBroadcastStream() .where((e) => e is Map) .map((e) => VpnStatsEvent.fromNativeMap( Map.from(e as Map), - )); + )) + .asBroadcastStream(); + + @override + Stream get statusStream => _statusStream; + + @override + Stream get statsStream => _statsStream; @override void dispose() {