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

Flutter HTTP请求无网络时未抛出异常问题求助

解决Flutter HTTP请求无网络时不立即抛异常的问题

默认的http.get方法在WiFi已连接但无实际网络、或中途断网时,不会立刻抛出SocketException,而是等待整体超时触发TimeoutException——原因是TCP握手会持续重试,直到系统级超时。可以通过以下几种方式解决:

方法1:自定义HttpClient设置连接超时

给底层HttpClient设置更短的连接超时,让网络异常更早触发:

import 'dart:io';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';

Future<http.Response> getWithEarlyNetworkCheck(Uri url, {Map<String, String>? headers}) async {
  final client = http.Client();
  try {
    // 配置HttpClient的连接超时,3秒内未建立连接则抛异常
    final httpClient = HttpClient()
      ..connectionTimeout = const Duration(seconds: 3)
      ..idleTimeout = const Duration(seconds: 3);
    client.httpClient = httpClient;

    final response = await client.get(url, headers: headers).timeout(const Duration(seconds: 20));
    return response;
  } on SocketException catch (e, st) {
    debugPrint('SocketException: 无有效网络连接');
    debugPrint(e.toString());
    debugPrint('系统错误码: ${e.osError?.errorCode}');
    rethrow;
  } on TimeoutException catch (_) {
    debugPrint('请求超时');
    rethrow;
  } catch (e, st) {
    debugPrint('未知错误: $e');
    rethrow;
  } finally {
    client.close();
  }
}

方法2:提前检测实际网络连通性

使用connectivity_plus检测设备连接状态,再通过请求一个极小的公共资源验证实际连通性:

  1. 添加依赖:
dependencies:
  connectivity_plus: ^5.0.1
  1. 实现检测方法:
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:http/http.dart' as http;
import 'package:flutter/foundation.dart';

Future<bool> hasValidNetwork() async {
  // 先检测设备连接状态
  final connectivityResult = await Connectivity().checkConnectivity();
  if (connectivityResult == ConnectivityResult.none) {
    return false;
  }
  // 请求极小资源验证实际连通性(国内可替换为百度图标:https://www.baidu.com/favicon.ico)
  try {
    final response = await http.get(Uri.parse('https://www.google.com/favicon.ico'))
        .timeout(const Duration(seconds: 2));
    return response.statusCode == 200;
  } catch (_) {
    return false;
  }
}

// 调用示例
try {
  final isConnected = await hasValidNetwork();
  if (!isConnected) {
    throw SocketException('无有效网络连接');
  }
  final response = await http.get(url, headers: headers).timeout(const Duration(seconds: 20));
} on SocketException catch (e, st) {
  debugPrint('SocketException: 无网络可用');
  debugPrint(e.toString());
  debugPrint('系统错误码: ${e.osError?.errorCode.toString()}');
} catch (e, st) {
  debugPrint('请求发生未知错误: $e');
}

方法3:使用Dio库(推荐)

Dio库支持单独配置连接超时和接收超时,异常类型更清晰,便于统一处理:

  1. 添加依赖:
dependencies:
  dio: ^5.4.0
  1. 配置并发起请求:
import 'package:dio/dio.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';

final dio = Dio(BaseOptions(
  connectTimeout: const Duration(seconds: 3), // 连接超时,3秒未建立连接则抛异常
  receiveTimeout: const Duration(seconds: 20), // 数据接收超时
));

Future<Response> fetchData(String url, {Map<String, String>? headers}) async {
  try {
    final response = await dio.get(url, options: Options(headers: headers));
    return response;
  } on DioException catch (e) {
    if (e.type == DioExceptionType.connectionError || e.type == DioExceptionType.connectionTimeout) {
      debugPrint('网络连接异常: ${e.message}');
      // 转换为SocketException保持原有错误处理逻辑
      throw SocketException(e.message ?? '无网络连接');
    } else if (e.type == DioExceptionType.receiveTimeout) {
      debugPrint('数据接收超时');
      rethrow;
    } else {
      debugPrint('请求错误: ${e.message}');
      rethrow;
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 01:45:56