You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中UDP发送抛出未捕获异常?明明已用try-catch处理

问题根源

模拟器锁屏时UDP发送失败是预期行为,但你用try-catch抓不到SocketException,本质原因是:
_RawDatagramSocket.send()虽然是同步方法,但底层Native实现碰到系统权限限制(比如锁屏后系统临时收回网络权限)时,异常会在异步的Isolate消息处理流程里抛出,不在你调用send()的同步代码上下文里,所以外层try-catch根本逮不到它。从报错栈也能看出来,异常最终是在_Timer._runTimers的Isolate消息回调里抛出来的,属于异步任务的未处理异常。

解决办法

1. 监听UDP Socket的错误流

_RawDatagramSocket是Stream类型,直接监听它的错误事件就能捕获底层异常:

// 初始化Socket的时候加上错误监听
_udpSocket!.listen(
  (event) {
    // 处理正常的Socket事件,比如接收数据
  },
  onError: (error) {
    print("UDP发送失败: $error");
    // 这里写你的错误处理逻辑,比如重试、缓存数据包
  },
);

2. 用runZonedGuarded兜住所有异步异常

因为你的发送逻辑是在Future.delayed这类异步回调里执行的,用runZonedGuarded可以把整个Zone里的未处理异步异常一网打尽:

runZonedGuarded(() {
  // 把包含UDP发送的异步逻辑都放在这个Zone里
  Future.delayed(Duration(milliseconds: 100), () {
    try {
      _udpSocket!.send(_packet, _serverAddress!, Server_UdpPort);
    } catch (e) {
      // 这里抓同步抛出的异常,异步的交给下面的回调处理
      print("同步异常: $e");
    }
  });
}, (error, stackTrace) {
  print("捕获到异步未处理异常: $error");
  print(stackTrace);
});

3. 提前监听锁屏状态,从源头避免异常

直接用插件监听设备锁屏状态,锁屏时暂停发送,解锁后再补发,根本不让错误发生:

// 示例用flutter_screen_state插件,需要先在pubspec里依赖
ScreenState.instance!.addListener((event) {
  if (event == ScreenStateEvent.SCREEN_OFF) {
    _isLocked = true;
  } else if (event == ScreenStateEvent.SCREEN_ON) {
    _isLocked = false;
    _sendPendingPackets(); // 补发锁屏期间缓存的数据包
  }
});

// 发送前先判断锁屏状态
if (!_isLocked) {
  _udpSocket!.send(_packet, _serverAddress!, Server_UdpPort);
} else {
  _pendingPackets.add(_packet); // 缓存起来等解锁再发
}
额外提醒
  • send()是同步方法,加await没用,别白费功夫。
  • 模拟器的权限逻辑和真机可能不一样,建议在真机上测试验证。

内容的提问来源于stack exchange,提问作者Greenlight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 04:10:41