Flutter中http.get()连接无互联网网络时无异常的问题求助
解决Flutter中http.get()在无互联网网络下无限挂起的问题
问题根源
connectivity_plus只能检测设备是否连接到Wi-Fi/蜂窝网络,但无法验证该网络是否能实际访问互联网。当设备连接到无权限访问互联网的网络时,http.get()会因无法建立有效连接而无限挂起,不会主动抛出异常。
解决方案
1. 预检测网络连通性(而非仅连接状态)
不要只依赖connectivity_plus的连接状态,发起请求前先做一次实际的连通性测试,比如ping可靠的公共DNS服务器,确认网络能访问互联网:
import 'dart:io'; Future<bool> hasInternetAccess() async { try { final result = await InternetAddress.lookup('8.8.8.8'); return result.isNotEmpty && result[0].rawAddress.isNotEmpty; } on SocketException catch (_) { return false; } }
在下载图片前调用该方法,提前拦截无效请求:
Future<void> downloadImage(String url) async { final canAccessInternet = await hasInternetAccess(); if (!canAccessInternet) { print('当前网络无法访问互联网'); // 这里更新UI提示用户网络异常 return; } // 执行后续下载逻辑 try { final response = await http.get(Uri.parse(url)); if (response.statusCode == 200) { // 处理下载成功的图片 } else { print('下载失败,状态码:${response.statusCode}'); } } on SocketException catch (e) { print('网络连接异常:$e'); } catch (e, stackTrace) { print('下载图片出错:$e'); print('堆栈跟踪:$stackTrace'); } }
2. 使用CancelToken主动终止挂起的请求
如果请求已经发起,可通过http包的CancelToken,在检测到网络失效时主动取消请求,避免无限挂起:
import 'dart:io'; import 'package:http/http.dart' as http; import 'package:connectivity_plus/connectivity_plus.dart'; class ImageDownloadManager { final http.CancelToken _cancelToken = http.CancelToken(); Future<void> startDownload(String url) async { // 先做连通性检测 if (!await hasInternetAccess()) { print('无互联网访问权限'); return; } // 监听网络状态变化 final networkSubscription = Connectivity().onConnectivityChanged.listen((_) async { if (!await hasInternetAccess() && !_cancelToken.isCancelled) { _cancelToken.cancel(); networkSubscription.cancel(); } }); // 执行下载 try { final response = await http.get(Uri.parse(url), cancelToken: _cancelToken); if (response.statusCode == 200) { // 处理图片 } else { print('下载失败,状态码:${response.statusCode}'); } } on http.CanceledException catch (_) { print('请求已取消'); } on SocketException catch (e) { print('网络连接异常:$e'); } catch (e, stackTrace) { print('下载出错:$e'); print('堆栈跟踪:$stackTrace'); } finally { networkSubscription.cancel(); } } }
3. 可选:给http客户端配置超时(补充方案)
如果能接受短超时,可给http客户端设置超时时间,强制终止长时间挂起的请求:
final http.Client client = http.Client()..timeout = const Duration(seconds: 10); try { final response = await client.get(Uri.parse(url), cancelToken: _cancelToken); // 处理响应 } on TimeoutException catch (_) { print('请求超时'); }
总结
- 预检测连通性可避免发起无效请求,减少资源浪费
- CancelToken能在网络状态动态变化时主动终止请求,解决无限挂起问题
- 结合
connectivity_plus的监听,可实时响应网络状态变更
内容的提问来源于stack exchange,提问作者Prinal Patel
相关产品推荐
相关产品推荐

