Flutter 与 pub.dev 依赖拉不下来:flutter pub get 超时、SDK 下载失败与镜像变量全解
新建一个 Flutter 项目,执行 flutter create 之后的第一步往往就停住了:终端显示「Running "flutter pub get" in my_app...」然后再无动静,几分钟后吐出「Got socket error trying to find package xxx at https://pub.dev」或者「SocketException: Connection timed out」。也有人卡得更早,刚解压 SDK 执行 flutter doctor,就停在「Downloading Dart SDK from Flutter engine」或「Downloading Material fonts」。好不容易包拉下来了,flutter run 又停在「Running Gradle task 'assembleDebug'...」十几分钟。
这三处卡住的原因各不相同。SDK 与引擎产物来自 storage.googleapis.com,Dart 包来自 pub.dev 及其背后的存储,Gradle 依赖来自 Google Maven 与 Maven Central。镜像变量只能管前两段,Gradle 要单独配置;而 Dart 命令行读的是环境变量里的代理,不一定跟随系统代理。把三段分开处理,比反复删缓存重试有效得多。
三段下载分别走哪里
这张表说明了一件事:Flutter 的「依赖下载失败」不是一个问题,而是五六个主机的问题。镜像变量只覆盖引擎产物和 pub 包两段,设置之后 Gradle 依然走官方仓库。所以排查时先看终端停在哪一行,再决定改哪一处,而不是把能找到的变量全部贴进环境。
| 下载内容 | 默认主机 | 可用镜像变量 | 典型报错 |
|---|---|---|---|
| Flutter SDK 源码 | github.com/flutter/flutter | 无,可直接下压缩包 | git clone 中断 |
| 引擎与 Dart SDK 产物 | storage.googleapis.com | FLUTTER_STORAGE_BASE_URL | Downloading Dart SDK 卡住 |
| pub 包索引与归档 | pub.dev | PUB_HOSTED_URL | Got socket error trying to find package |
| Android Gradle 依赖 | dl.google.com、repo.maven.apache.org | 需改 Gradle 仓库配置 | Could not resolve com.android.tools.build:gradle |
| Gradle 本体 | services.gradle.org | 改 distributionUrl | Exception in thread main 下载超时 |
| iOS CocoaPods | cdn.cocoapods.org、github.com | 改 Podfile 的 source | pod install 卡在 Analyzing dependencies |
从卡住到能跑:分步操作
- 第一步:先把网络线路准备好。安装刺猬VPN,自定义用户名和密码注册,不需要邮箱和手机号,连上后先用浏览器打开 pub.dev 和 storage.googleapis.com,两个都能打开再回到终端。免费节点永久免费、不限流量、不限速,够用来判断问题是不是出在网络;
- 第二步:确认终端能用上线路。Dart 与 Flutter 命令行读取环境变量 HTTP_PROXY、HTTPS_PROXY 与 NO_PROXY,未必跟随系统代理。Windows PowerShell 里用 $env:HTTPS_PROXY 设置,macOS 与 Linux 写进 ~/.zshrc 或 ~/.bashrc,NO_PROXY 至少写上 localhost,127.0.0.1,否则调试时连本机模拟器也会绕出去;
- 第三步:执行 flutter doctor -v,看每一项的详细输出。停在 Downloading 开头的行,是引擎产物没下完;显示「Android toolchain」有叉,是 SDK 路径或许可证问题,与 pub 无关,处理方法见 Android SDK 那一篇;
- 第四步:引擎产物下载失败时,删除 Flutter SDK 目录下 bin/cache 文件夹后重新执行 flutter precache。只删 cache,不要删整个 SDK,否则还要重新 clone;
- 第五步:进入项目目录执行 flutter pub get。若仍报 socket error,用 dart pub get --verbose 看最后一次请求的完整地址,确认是索引请求失败还是归档文件下载失败;
- 第六步:依赖解析失败而不是网络失败时,报错会写「Because my_app depends on xxx which requires SDK version」,这是版本约束冲突,改 pubspec.yaml 的版本号或执行 flutter pub upgrade --major-versions,与线路无关;
- 第七步:缓存损坏时执行 dart pub cache repair,它会重新下载缓存里每一个包。缓存目录在 Windows 是 %LOCALAPPDATA%\Pub\Cache,macOS 与 Linux 是 ~/.pub-cache;
- 第八步:Android 端停在 assembleDebug 时,打开 android/gradle/wrapper/gradle-wrapper.properties 看 distributionUrl 指向的 Gradle 版本,确认 services.gradle.org 能访问;Gradle 不读 HTTPS_PROXY,要在 android/gradle.properties 里写 systemProp.https.proxyHost 与 systemProp.https.proxyPort;
- 第九步:全部通过后执行 flutter run,首次构建较慢属于正常,第二次会快很多。
按卡住的那一行排查
- Waiting for another flutter command to release the startup lock:上一个 flutter 进程没退出,结束所有 dart 与 flutter 进程,必要时删除 bin/cache/lockfile 再试;
- Downloading Dart SDK from Flutter engine 卡住:storage.googleapis.com 不通,确认线路后删 bin/cache 重下,或临时设置 FLUTTER_STORAGE_BASE_URL 指向镜像;
- Got socket error trying to find package:pub.dev 请求失败,检查 HTTPS_PROXY 是否在当前终端生效,用 echo 打印一次变量确认;
- HandshakeException 或 CERTIFICATE_VERIFY_FAILED:中间有程序替换了证书,常见于杀毒软件的 HTTPS 扫描或公司网络,关掉扫描或换网络;
- pub get 成功但 IDE 仍标红:IDE 用的是另一份 Flutter SDK,在设置里把 Flutter SDK path 指向同一目录,然后重启 Dart 分析服务;
- Could not resolve com.android.tools.build:gradle:Gradle 到不了 Google Maven,配置 gradle.properties 的代理或在 settings.gradle 里调整仓库顺序;
- pod install 卡在 Analyzing dependencies:CocoaPods 的规格仓库下载慢,先执行 pod repo update,确认 cdn.cocoapods.org 能访问。
官方源、镜像与线路怎么选
镜像的好处是不需要代理,坏处是只管两段、可能滞后,而且 dart pub publish 不能走镜像。团队里有人发布自己的包,或者依赖刚发布的新版本,直连官方更省心。刺猬VPN支持按域名的智能分流,可以只让 pub.dev、storage.googleapis.com、dl.google.com 这几个域名走线路,国内服务照常直连。实际可用性取决于当前网络环境。
| 对比项 | 会员节点直连官方 | 社区镜像 | 免费节点 |
|---|---|---|---|
| 包的新鲜度 | 与 pub.dev 实时一致 | 可能延迟数小时 | 与官方一致 |
| 覆盖范围 | SDK、pub、Gradle 全部 | 只覆盖 pub 与引擎产物 | 全部,但负载不定 |
| 配置成本 | 设一次代理变量 | 设两个镜像变量 | 同左 |
| 发布包 | dart pub publish 可用 | 不支持发布 | 可用 |
| 流量 | 时长套餐有效期内不限流量、不限速 | 由镜像决定 | 永久免费、不限流量、不限速 |
| 适合场景 | 日常开发与发布 | 只需拉包且能接受延迟 | 先判断是不是网络问题 |
Windows、macOS 与持续集成的差异
Windows 上最常见的坑是环境变量只设在当前 PowerShell 窗口里,换个窗口或在 Android Studio 里点运行就失效了。长期使用要在「系统属性」的「环境变量」里设置用户变量,并重启 IDE。路径里有中文或空格时,Gradle 偶尔会报奇怪的路径错误,把 Flutter SDK 放在 C:\src\flutter 这样的纯英文路径更稳。
macOS 上 Android Studio 从 Dock 启动时不会读取 ~/.zshrc,所以终端里能跑、IDE 里报 socket error。可以从终端用 open -a "Android Studio" 启动,让它继承终端的变量。持续集成机器没有图形界面,把代理或镜像变量写进流水线的环境配置,并缓存 ~/.pub-cache 与 ~/.gradle,第二次构建就不必重新下载。Linux 上用 snap 安装的 Flutter 有自己的沙箱,环境变量和缓存位置都与手动安装不同,遇到奇怪的权限或路径报错时,改用官方压缩包手动安装往往更省事。无论哪个系统,改完变量都要新开终端再验证,旧窗口里的变量不会自动刷新。
锁文件、缓存与团队协作
很多「别人能拉、我拉不下」的情况,其实不是网络问题,而是锁文件不一致。pubspec.lock 记录了每个依赖解析出来的确切版本,应用项目应当把它提交进仓库,这样所有人拉到的是同一组版本;插件或库项目则通常不提交,让使用者自己解析。如果同事改过依赖却没提交锁文件,你执行 pub get 时就会重新解析,可能解析到一个刚发布、镜像还没同步的版本,看起来就像下载失败。
缓存目录是全机共享的,同一台电脑上的多个项目会复用已经下载过的包。这意味着一旦某个包的归档下载到一半被中断,所有用到它的项目都会报同样的错,删项目里的 .dart_tool 文件夹没有用,要执行 dart pub cache repair 或者直接删掉缓存里那一个包的目录。缓存体积会随时间增长到几个 GB,执行 dart pub cache clean 可以整体清空,但下次每个项目都要重新下载,最好在线路稳定时再做。
团队里统一一份说明:Flutter 版本用哪个渠道、SDK 放在什么路径、代理或镜像变量怎么写、Gradle 的代理写在哪个文件。新成员第一次配置环境时,严格按说明顺序执行,每一步都看到成功提示再进入下一步。出现问题时,先报告终端停在哪一行、执行的是哪个命令,而不是笼统地说「依赖下载不了」,这样别人能直接判断是哪一段的问题。
Web、桌面端与版本切换带来的额外下载
只做手机端时,引擎产物下载一次就够了;一旦执行 flutter config --enable-web 或启用 Windows、macOS 桌面支持,下次构建时 Flutter 会再去下载对应平台的引擎产物,又会碰到一次 storage.googleapis.com。很多人以为环境早就配好了,结果第一次构建桌面版又卡住,原因就在这里。启用新平台后先执行一次 flutter precache --web 或对应参数,把产物提前拉好。
切换版本渠道也一样。执行 flutter channel beta 或 flutter upgrade 时,Flutter 会通过 Git 拉取新代码,再重新下载整套引擎产物,Git 那一段走的是 github.com,与 pub 的变量无关。用版本管理工具同时维护多个 Flutter 版本时,每个版本都有自己的 bin/cache,第一次切换到某个版本时都要完整下载一遍,所以不要在网络不稳的时候切换版本。升级失败时,先执行 git status 看 SDK 目录有没有被改过,被改动的文件会让升级中途停下。
迁移到新电脑时的顺序
- 先装 Git 并确认能访问 github.com,再下载 Flutter SDK 压缩包或 clone 稳定渠道;
- 把 SDK 的 bin 目录加入路径,新开终端执行 flutter --version,看到版本号再继续;
- 设置代理或镜像变量,执行 flutter precache,让引擎产物一次下完;
- 安装 Android SDK 并接受许可证,flutter doctor 的 Android 一项变成绿勾;
- 最后进入项目执行 flutter pub get 与 flutter run,不要把旧电脑的缓存目录整个拷过来,版本不一致反而更难排查。
和其他开发下载工具的分工
Flutter 的 Android 端依赖完整的 Android SDK,sdkmanager 拉不下清单、许可证没接受、cmdline-tools 目录放错,这些与 pub 无关,处理方法见 Android SDK 下载失败排查。先让 flutter doctor 的 Android toolchain 变成绿勾,再处理 pub。
如果你同一台电脑上还要用 npm、pip、Docker,它们各有自己的镜像和代理变量,不要用 Flutter 的变量去修它们,统一的思路见 npm、pip、Docker 拉取失败排查。每个工具只改自己的配置,出问题时才能快速定位是哪一段。验收标准很简单:新开终端执行 flutter doctor 全部通过,pub get 与 flutter run 各成功一次。
常见报错速查表
| 现象 | 原因 | 解决办法 |
|---|---|---|
| Got socket error trying to find package | 到不了 pub.dev | 确认 HTTPS_PROXY 在当前终端生效 |
| Downloading Dart SDK 卡住 | 引擎产物主机不通 | 删 bin/cache 后 flutter precache |
| startup lock 等待 | 旧进程未退出 | 结束 dart 进程,删 lockfile |
| CERTIFICATE_VERIFY_FAILED | 证书被中间程序替换 | 关闭 HTTPS 扫描或换网络 |
| requires SDK version | 版本约束冲突 | 改 pubspec 版本号 |
| Could not resolve gradle | Gradle 不读代理变量 | 在 gradle.properties 配代理 |
| IDE 标红但命令行正常 | IDE 用了另一份 SDK | 统一 Flutter SDK path |
高频问答
- 问:设置了系统代理为什么 pub 还是超时?答:Dart 命令行读的是 HTTPS_PROXY 等环境变量,系统代理不一定生效,在终端里显式设置一次;
- 问:镜像和代理能同时用吗?答:可以,但没必要,镜像变量会让 pub 绕开 pub.dev,出问题时更难判断是哪一边;
- 问:flutter clean 能解决下载问题吗?答:不能,它只清项目构建产物,不碰 pub 缓存与引擎缓存;
- 问:为什么第一次 flutter run 特别慢?答:首次要下载 Gradle 本体和全部 Android 依赖,几百 MB 很正常,之后会走本地缓存;
- 问:能只给 Android Studio 走线路吗?答:客户端没有按应用勾选的功能,用按域名的智能分流覆盖相关下载域名即可;
- 问:免费节点够用吗?答:够判断网络问题,首次拉全量依赖建议用时长套餐,有效期内不限流量、不限速。
把环境一次配稳
Flutter 与 pub.dev 依赖下载失败,拆开看是 SDK 产物、pub 包、Gradle 依赖三段各自的问题。先让浏览器能打开对应主机,再让终端变量生效,最后单独给 Gradle 配代理;每改一处就重跑一次对应命令,确认这一段通了再动下一段。团队文档里写清 SDK 路径、变量和缓存目录,新人照着做就不会重复踩坑。
刺猬VPN采用 HTTPS+AES 加密传输,自定义用户名和密码即可匿名注册,不需要邮箱和手机号;免费节点永久免费、不限流量、不限速;时长套餐有效期内不限流量、不限速,客户端支持按域名与 IP 的智能分流和断线保护,一个账号可在多台开发机上使用。依赖能否顺利下载取决于当前网络环境。
换刺猬VPN告别连接烦恼:一键连接、连接稳定
刺猬VPN提供永久免费节点,不限流量;无需邮箱,自定义用户名即可匿名注册。一个账号支持多设备同时在线,实际可用性取决于当前网络环境。