如何在Flutter中缓存DNS查询、TCP握手、SSL握手等网络元素优化请求速度
Flutter网络请求握手耗时优化方案
你当前遇到的高耗时问题核心原因是:默认调用http.get()快捷方法时,每次请求都会创建新的http.Client实例,请求结束后直接销毁关联连接,无法复用之前的DNS查询、TCP握手、SSL握手结果,每次请求都要重新走完整的连接流程。
可通过以下方案优化:
方案1:复用原生http.Client实例
同一http.Client实例发起的同域名请求,底层会自动做连接池管理,默认空闲连接会保留15秒,有效期内的后续请求直接复用已有连接,无需重复握手。
修改后的代码示例如下:
class RoleService with ChangeNotifier { NavLinks _navLinks = NavLinks(); late List<Role> _roles; // 全局持有同一个http.Client实例,不要每次请求新建 final http.Client _sharedClient = http.Client(); List<Role> returnRoles() { return _roles; } Future<void> getAllRoles(String authToken) async { try { // 用持有的_sharedClient发起请求,不要用http.get快捷方法 var data = await _sharedClient.get( Uri.parse(_navLinks.getAllRoles()), headers: {HttpHeaders.authorizationHeader: "Bearer $authToken"}, ); var jsonData = convert.json.decode(data.body).cast<Map<String, dynamic>>(); _roles = jsonData.map<Role>((json) => Role.fromJson(json)).toList(); } catch (error) { print(error); rethrow; } } // 页面/服务销毁时调用关闭连接即可 @override void dispose() { _sharedClient.close(); super.dispose(); } }
方案2:使用dio网络库做更灵活的配置
如果需要自定义连接池参数、DNS缓存等更进阶的优化,可以使用dio库,默认自带连接复用能力,可配置项更丰富:
import 'package:dio/dio.dart'; class ApiService { // 全局单例dio实例 static final Dio _dio = Dio( BaseOptions( baseUrl: "你的API统一根地址", connectTimeout: Duration(seconds: 5), receiveTimeout: Duration(seconds: 3), ), )..httpClientAdapter = IOHttpClientAdapter( // 自定义空闲连接保留时长,可根据业务场景调整 idleTimeout: Duration(minutes: 2), ); Future<void> getAllRoles(String authToken) async { final response = await _dio.get( "/roles接口相对路径", options: Options(headers: {"Authorization": "Bearer $authToken"}), ); // 后续数据解析逻辑和之前一致 } }
额外优化建议
- 所有请求必须使用同一个全局Client/dio实例才能实现连接复用,不要每次请求新建实例
- 可以在应用启动阶段提前对目标域名做一次预请求,提前完成DNS、握手缓存,用户实际触发请求时直接复用
- 若服务端支持HTTP2,连接复用效率会更高,dio原生支持HTTP2协议
内容的提问来源于stack exchange,提问作者PeakGen
相关产品推荐
相关产品推荐

