Flutter网络检测状态异常导致sendEmail触发SocketException
问题根因
- 异步调用未等待结果:
checkUserConnection()是返回Future的异步方法,你在onTap回调中直接调用时没有加await等待执行完成,调用后会立刻往下执行activeConnection的判断逻辑。此时DNS域名检测的逻辑还在后台运行,activeConnection还是上一次检测留存的true值,根本没拿到最新的断网状态,就直接触发了sendEmail(),自然会报主机查找失败的异常。 - 同步
sleep完全无效:你之前加的sleep(const Duration(seconds: 10))是同步阻塞方法,会卡住当前主Isolate的所有事件循环(包括网络IO、UI更新、DNS查询),不仅不会给网络状态切换留缓冲时间,反而会让检测逻辑卡到sleep结束后才执行,而外层的判断逻辑根本不会等sleep跑完,完全起不到等待作用。 - 缺乏异常兜底:你把前置网络检测作为判断能否发邮件的唯一依据,但网络状态本身是随时可变的——就算检测时网络正常,发送邮件的过程中也可能出现断网、DNS解析失败的问题,没有给
sendEmail()加异常捕获的话,任何网络波动都会直接抛出未捕获异常。
修复方案
- 调整异步调用逻辑,必须等待检测完成再执行后续判断:把
onTap回调改成async函数,调用checkUserConnection()时加await,等检测完全结束拿到结果后再判断是否发邮件。同时优化checkUserConnection的返回值,直接返回布尔类型的网络状态结果,不要依赖类成员变量传值,从根源上避免时序导致的状态不一致问题。 - 替换无效的同步sleep:如果需要给网络状态切换留几百毫秒的系统同步缓冲时间,用非阻塞的
await Future.delayed(),不会卡住事件循环。 - 给邮件发送逻辑加异常兜底:
sendEmail()执行时必须捕获SocketException等网络相关异常,就算前置检测通过,发送过程中出现网络问题也能友好提示,不会直接崩溃。 - 可选优化:如果需要更实时的网络状态感知,不要每次点击才临时做DNS lookup,可以监听系统网络切换的系统广播,实时维护网络连接状态,比临时DNS查询响应更快、误判率更低。
修复后参考代码
网络检测方法
Future<bool> checkUserConnection() async { try { // 非阻塞延时300ms,给系统留网络状态切换的同步时间 await Future.delayed(const Duration(milliseconds: 300)); // 实际发邮件用的是smtp.gmail.com,直接检测该域名连通性更准确 final result = await InternetAddress.lookup('smtp.gmail.com'); final isConnected = result.isNotEmpty && result[0].rawAddress.isNotEmpty; setState(() { activeConnection = isConnected; }); return isConnected; } on SocketException catch (_) { setState(() { activeConnection = false; }); return false; } }
点击触发逻辑
onTap: () async { // 等待检测完成,拿到最新的网络状态 final isConnected = await checkUserConnection(); if (isConnected) { try { await sendEmail(); ScaffoldMessenger.of(context).showSnackBar(showSnackBar( false, "email sended ", Icons.check_circle)); } on SocketException catch (_) { // 发送过程网络异常的兜底提示 ScaffoldMessenger.of(context).showSnackBar(showSnackBar( true, "send failed, please check your internet connection", Icons.error_outline)); } } else { ScaffoldMessenger.of(context).showSnackBar(showSnackBar( true, "check your internet connection !!!", Icons.error_outline)); } },
内容的提问来源于stack exchange,提问作者abr ahm
相关产品推荐
相关产品推荐

