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

Flutter iOS真机首次安装正常,后续启动网络异常重启4次恢复

Flutter iOS真机网络请求异常:资源泄漏导致的文件句柄耗尽问题

问题现象

  • 数据密集型Flutter App(包含API接口请求、地图瓦片加载)在Android、iOS模拟器、Windows平台运行正常,但**iOS真机(Debug/Release模式)**出现以下异常:
    1. 首次安装启动时无问题,数据加载、地图瓦片渲染流畅;
    2. 后续启动频繁出现数据缺失、地图瓦片加载失败;
    3. 调试器捕获大量两类错误:
      Error: SocketException: Failed host lookup: 'site.com' (OS Error: nodename nor servname provided, or not known, errno = 8) 
      Error: SocketException: Connection failed (OS Error: Too many open files, errno = 24), address = site.com, port = 443 
      
    4. 同一域名下的10次左右API/JSON请求无失败,仅数百次地图瓦片请求报错;App顶层网络检测显示目标站点可正常访问。

已执行的排查操作

  • 测试了直接安装、TestFlight安装两种分发方式,问题均复现;
  • 覆盖iPhone 11、iPhone 15两款设备;
  • 所有系统软件、Flutter依赖包已更新至最新版本;
  • 切换使用过http、dio两种网络请求包;
  • 尝试在AppLifecycleState.detached状态下调用exit(0)强制退出;
  • 排查IPv4/IPv6兼容性:切换至LTE网络曾短暂恢复正常,但5G网络仍存在问题;仅连续重启App 4次可重置状态,恢复正常运行。

核心原因分析

1. 首次正常、后续异常的本质

这是iOS平台下Dart网络层的资源泄漏导致的:

  • 首次启动时,App的文件句柄、网络套接字资源处于初始状态,未达到系统限制(iOS单进程默认文件句柄上限约1024);
  • 后续启动时,前一次App退出后,大量地图瓦片的并发请求未被正确释放,残留的套接句柄累积占用资源,最终触发Too many open files错误。当文件句柄耗尽时,DNS解析请求也无法获取资源,进而引发nodename nor servname provided的域名解析失败。

2. 连续重启4次恢复的逻辑

iOS对App的资源回收采用渐进式清理策略:

  • 前几次重启时,系统可能仍保留了App的部分残留资源;
  • 连续重启4次后,系统判定该App存在异常资源泄漏,会强制清理所有与该App关联的套接字、文件句柄、缓存资源,让App重新获取完整的资源配额,因此恢复正常。

3. 与Dart网络包的关联

目前Dart的http包存在已知的类似资源泄漏问题,在iOS真机环境下,高频并发的小请求(如地图瓦片)会导致套接字无法及时回收,累积后触发资源耗尽。

解决方案

  1. 限制并发请求数量
    地图瓦片属于高频并发请求,需限制同时发起的请求数(建议设置为10-20),避免瞬间耗尽文件句柄:

    • 使用dio可通过自定义拦截器或设置Transformer控制并发;
    • 使用http可结合async库的Semaphore实现并发限流。
  2. 主动释放网络资源

    • 对于http包,确保每个请求的Response都被正确关闭,可使用await using语法自动管理资源:
      await using((client) async {
        final response = await client.get(Uri.parse('https://site.com/tile'));
        // 处理响应
      }, HttpClient.new);
      
    • 对于地图组件(如flutter_map、google_maps_flutter),在App退居后台时,主动调用组件的资源清理方法,取消未完成的瓦片请求。
  3. 优化App退出逻辑
    不要仅依赖exit(0),在AppLifecycleState.paused或detached状态下,主动取消所有未完成的网络请求:

    • 使用dio时,调用CancelToken.cancel()取消请求;
    • 关闭所有HttpClient或Dio实例,确保资源被释放。
  4. 完善iOS网络配置
    在Info.plist中添加NSAppTransportSecurity配置,确保IPv6兼容性,避免DNS解析异常:

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>site.com</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSAllowsArbitraryLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>
    
  5. 切换至原生网络请求
    若Dart层的资源泄漏问题无法解决,可通过MethodChannel调用iOS原生的URLSession实现网络请求,原生层的资源管理机制更成熟,能有效避免此类泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 07:01:14