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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 13:45:11