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

如何缩短Flutter中API请求的连接等待时间?

解决Flutter API请求连接延迟问题

一、核心问题定位

你遇到的200ms连接等待,大概率是TCP连接建立+SSL握手的重复开销——Postman和浏览器会默认复用连接(HTTP/1.1的Keep-Alive或HTTP/2多路复用),但Flutter默认的HTTP客户端可能未正确配置长连接复用,或缺少DNS/SSL会话缓存。

二、具体解决方案

1. 优化Dio的连接复用配置

既然使用Dio,直接配置其HttpClientAdapter强制开启长连接与连接池,比原生http.Client更灵活:

import 'package:dio/dio.dart';
import 'package:dio/io.dart';

// 创建全局复用的优化版Dio实例
Dio createOptimizedDio() {
  final dio = Dio();
  dio.httpClientAdapter = IOHttpClientAdapter(
    createHttpClient: () {
      final client = HttpClient();
      // 设置连接空闲超时,保持长连接30秒
      client.idleTimeout = const Duration(seconds: 30);
      // 单主机最大并发连接数,按需调整
      client.maxConnectionsPerHost = 10;
      // 启用SSL会话复用
      client.badCertificateCallback = (cert, host, port) => false;
      return client;
    },
  );
  // 显式声明长连接
  dio.options.headers['Connection'] = 'keep-alive';
  return dio;
}

// 全局复用该实例,不要每次请求新建
final dio = createOptimizedDio();

// 使用示例
final response = await dio.get('你的API地址');

2. 原生http.Client的进阶优化

如果坚持用原生库,需手动配置底层HttpClient参数,且必须全局单例复用:

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

// 创建全局复用的优化版Client
final http.Client optimizedHttpClient = http.Client(
  HttpClient()
    ..idleTimeout = const Duration(seconds: 30)
    ..maxConnectionsPerHost = 10
    ..connectionTimeout = const Duration(seconds: 5),
);

// 使用时直接复用该client
final res = await optimizedHttpClient.get(Uri.parse('你的API地址'));

注意:每次请求新建Client会导致重复建立TCP/SSL连接,这是延迟的核心诱因之一。

3. 实现DNS缓存

Flutter默认HttpClient不缓存DNS解析结果,每次请求都要重新解析,会增加额外延迟。可通过自定义解析器实现缓存:

import 'dart:io';
import 'package:dio/dio.dart';
import 'package:dio/io.dart';

class DnsCache {
  static final Map<String, InternetAddress> _cache = {};
  static const Duration cacheTtl = Duration(minutes: 10);
  static final Map<String, DateTime> _expiryTime = {};

  static Future<InternetAddress> resolve(String host) async {
    // 检查缓存是否有效
    if (_cache.containsKey(host) && _expiryTime[host]!.isAfter(DateTime.now())) {
      return _cache[host]!;
    }
    // 重新解析并更新缓存
    final addresses = await InternetAddress.lookup(host);
    final address = addresses.first;
    _cache[host] = address;
    _expiryTime[host] = DateTime.now().add(cacheTtl);
    return address;
  }
}

// 配置Dio使用自定义DNS缓存
Dio createDioWithDnsCache() {
  final dio = Dio();
  dio.httpClientAdapter = IOHttpClientAdapter(
    onHttpClientCreate: (client) {
      client.resolve = (String host, int port, {Duration? timeout}) async {
        final address = await DnsCache.resolve(host);
        return [address];
      };
      client.idleTimeout = const Duration(seconds: 30);
      return client;
    },
  );
  return dio;
}

4. 强制SSL会话复用

SSL握手是连接延迟的主要来源,需确保客户端与服务器端同时配置:

  • 客户端:通过idleTimeout保持连接打开状态,避免重复握手;
  • 服务器端:配置SSL会话缓存(如Nginx的ssl_session_cache),配合客户端复用会话。

5. 启用HTTP/2

若服务器支持HTTP/2,FlutterHttpClient默认兼容,只需确保请求为HTTPS(HTTP/2通常要求HTTPS),并在Dio中声明:

// Dio中启用HTTP/2(若服务器支持)
dio.options.headers['Upgrade'] = 'h2c'; // 明文HTTP/2需配置,HTTPS环境可省略

HTTP/2的多路复用可让多个请求复用同一TCP连接,彻底消除连接等待。

三、验证优化效果

  • 用Flutter DevTools的Network面板重新测量,查看Connect时间是否降至100ms以内;
  • 对比多次请求的连接ID,若复用连接,ID会保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 05:22:49