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检测设备连接状态,再通过请求一个极小的公共资源验证实际连通性:
- 添加依赖:
dependencies: connectivity_plus: ^5.0.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库支持单独配置连接超时和接收超时,异常类型更清晰,便于统一处理:
- 添加依赖:
dependencies: dio: ^5.4.0
- 配置并发起请求:
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
相关产品推荐
相关产品推荐

