fvm多版本管理实战:Windows环境Flutter SDK切换与项目版本锁定指南
2026/9/17 5:37:57 网站建设 项目流程

1. 为什么要用fvm管理Flutter版本:本地多项目共存的现实问题

如果你同时维护几个Flutter项目,肯定遇到过这样的尴尬:项目A用的是Flutter 3.16,项目B因为历史依赖锁在了Flutter 3.7,项目C可能已经追新到了3.22。在没有fvm之前,常规做法就是不断卸载重装Flutter SDK,或者手动修改PATH环境变量指向不同版本的SDK目录。这套操作有多烦,经历过的人应该都有体会。

1.1 版本切换的原始痛点

先说说我自己踩过的坑。之前接了一个维护老项目的工作,项目依赖的某个插件包在Flutter 3.19之后就不再维护了,新版本API变动导致编译直接报错。当时我用的Flutter版本是3.24,为了跑这个项目只能忍痛降级。降级过程中先卸载旧版、删除缓存、重新下载3.7的SDK压缩包,再配置环境变量,前后折腾了两个多小时。等项目跑通之后,我自己的主项目又需要回到3.24,又重复了一遍卸载安装的流程。

这还只是麻烦层面的问题,更头疼的是缓存共用。Flutter的pub缓存默认是全局的,不同版本的Flutter共享同一个pub cache路径,版本跨度大了之后,经常出现某个包在3.7下编译正常、在3.24下却因为SDK版本约束直接被拒绝解析,导致两个项目的依赖互相污染。你刚把主项目跑起来,切回老项目就得重新pub get,而且很可能解析出一堆版本冲突。

1.2 fvm解决的核心问题

fvm(Flutter Version Management)的思路和nvm管理Node.js版本几乎一模一样,核心就三件事:一是把多个Flutter SDK版本集中存放在一个统一目录下互不干扰,二是在项目级别记录当前项目使用的Flutter版本,三是通过软链接或者环境变量切换实现一条命令快速换版本。

fvm的全称是Flutter Version Management,官方地址在fvm.app,GitHub仓库是leoafarias/fvm。它最实用的特性有三个:

  • 项目级版本锁定:在项目根目录执行fvm use 3.19.6之后,会生成一个.fvmrc文件,里面记录了当前项目需要的Flutter版本。后续任何人在这个项目里执行fvm install或者fvm use,fvm会自动读取配置并切换到对应版本,团队协作时消除了"我本地能跑你本地报错"的环境差异问题。

  • 全局默认版本管理fvm global 3.24.0可以设置系统默认的Flutter版本,新项目默认使用这个版本,不用每创建一个项目都手动切换。

  • SDK隔离存储:所有通过fvm安装的Flutter SDK都放在同一个根目录下(Windows默认是%USERPROFILE%\fvm\versions),每个版本独立存在,互不干扰。pub cache也做了版本隔离,不会出现依赖缓存串版本的问题。

2. Windows环境下fvm安装与初始化的完整过程

fvm的安装方式在不同平台上有区别,Windows下我推荐用包管理器安装,最简单省事。

2.1 通过Chocolatey安装fvm

如果你机器上已经装了Chocolatey,直接执行:

choco install fvm

装完之后重新打开一个PowerShell窗口,执行fvm --version确认安装成功。如果输出类似fvm 3.1.7的版本号,说明安装这一关过了。

没有Chocolatey的话,也可以用GitHub Release里提供的Windows安装包,下载最新版本的fvm-windows.zip,解压之后把可执行文件所在目录手动添加到系统PATH里。考虑到后续fvm还会自动维护一些内部命令,这个方式相对麻烦,建议还是先装Chocolatey一次性解决。

提示:确认安装成功后,先执行一次fvm doctor检查环境完整性。它会自动检测Git、Visual Studio构建工具、Android Studio这些Flutter开发的基础依赖是否就位,有问题会直接提示。

2.2 指定fvm的SDK存储目录

fvm默认会把所有版本的Flutter SDK存放在%USERPROFILE%\fvm\versions路径下。如果你有特殊需求,比如C盘空间紧张想放到其他盘,可以通过环境变量FVM_HOME来指定存储位置。我的做法是把fvm的SDK放到D盘开发目录下,这样即使系统重装,SDK还在,省去重新下载的时间:

# 先创建目录 mkdir D:\dev\fvm # 设置用户级环境变量 setx FVM_HOME "D:\dev\fvm"

设置完环境变量后需要重新打开终端窗口才能生效,然后执行fvm doctor验证一下是否读取到了新路径。

2.3 安装第一个Flutter版本

fvm本身只是管理工具,不附带任何Flutter SDK。需要先安装一个版本才能开始工作:

# 安装稳定版最新版本 fvm install stable # 或者指定具体版本号 fvm install 3.22.3 fvm install 3.19.6

fvm支持直接在命令中指定stablebeta这样的大版本通道,更推荐直接指定版本号,这样版本可追溯性更强。项目要求什么版本就安装什么版本,全部需求列成清单之后一条一条执行即可。

安装过程中fvm会从Flutter官方仓库下载对应版本的SDK压缩包并自动解压,耗时取决于网络状况,一般3.22这种体积的包大概需要5到10分钟。安装完成之后,执行:

fvm list

就能看到当前机器上所有已安装的Flutter版本列表。我本机现在就装了好几个版本,从3.7.12到3.24.5都有,各项目按需切换。

3. fvm的核心工作流:项目级版本锁定与全局版本切换

fvm日常使用频率最高的就是fvm usefvm global这两条命令。前者管项目,后者管全局,理解清楚这两个概念就不会用糊涂。

3.1 项目级版本绑定

在任何一个Flutter项目根目录下执行:

fvm use 3.19.6

fvm会做两件事:第一,检查本机是否已经安装了3.19.6,如果没有会自动提示并安装;第二,在当前项目目录下生成一个.fvmrc文件,内容长这样:

{ "flutter": "3.19.6" }

这个文件就是项目版本锁定的依据,建议提交到git仓库。团队其他成员拉取代码后,在项目里执行fvm use就会自动读取.fvmrc并切换到对应版本,不需要再去问"你们用的哪个版本"。

另外,执行fvm use时fvm还会在项目根目录生成一个.fvm文件夹,里面是一个指向真实SDK路径的软链接。这个文件夹一般不需要提交到git仓库,在.gitignore里加上.fvm/即可。

执行完fvm use之后有个容易忽略的问题:在当前终端窗口里Flutter命令并不会自动切换成fvm管理的版本。你还需要用fvm flutter来调用项目绑定的Flutter版本,或者用下面的方式重新打开终端让软链接生效。

3.2 fvm flutter与fvm dart的使用

在项目目录下,所有原本执行flutter命令的地方都要改成fvm flutter

fvm flutter pub get fvm flutter run fvm flutter build apk

fvm会自动读取当前项目.fvmrc中指定的版本去执行这些命令,不会用错。同样的,dart命令对应的是fvm dart

这个习惯刚开始确实不太容易适应,尤其是直接在项目根目录敲flutter run的时候,正确做法是敲fvm flutter run。不过适应期很短,因为fvm会在非项目目录执行时给出友好的提示信息,提醒你这是一个fvm管理的项目。

3.3 设置全局默认版本

不是所有场景都跟具体项目绑定。比如你新建一个测试项目,压根还没有执行fvm use,此时fvm默认调用的是全局版本。全局版本用这个命令设置:

fvm global 3.24.0

设置全局版本之后,fvm会在系统PATH中加入一个指向当前全局版本SDK的链接,让flutter命令可以直接使用,日常新建项目直接就能跑。

注意:fvm global切换的版本只在重新打开的终端窗口中生效,因为PATH环境变量在会话启动时就已经定下来了。另外,全局版本主要用于临时测试和新建项目,正经的正式项目还是建议在项目根目录执行fvm use把版本固化下来。全局版本的版本号修改后,所有未绑定版本的终端都会受影响,容易造成"刚才还能跑现在突然不行了"的假象。

4. Flutter版本升级与回退的实战操作

fvm的核心价值在版本升级和回退时体现得最明显。以前我升级Flutter版本最大的顾虑就是升级后发现项目编译不通过,想回退又要重新折腾一遍环境。有了fvm之后,升级再也不用"破釜沉舟"了。

4.1 升级到新版本

升级一个已有项目的Flutter版本,操作流程是这样的:

# 1. 安装新版本 fvm install 3.27.0 # 2. 项目切换 fvm use 3.27.0 # 3. 重新拉取依赖 fvm flutter pub get # 4. 跑一下测试和构建验证 fvm flutter analyze fvm flutter test fvm flutter build apk --debug

如果测试和构建都通过了,升级完成。如果报错,说明项目里有API变化或者依赖兼容性问题,此时只需要在你的项目代码里逐一修复即可,再也不用手忙脚乱地去卸载重装SDK了。

这里有个细节想分享下我的经验:每次升级的跨度不宜过大,从一个版本跳到隔了很多个版本的大跨度升级容易积累太多兼容性问题,排查起来麻烦。我一般是隔两三个小版本升一次,比如3.24升3.27,而不是从3.19直接跳到3.29。

4.2 回退到旧版本

回退比升级还简单,因为旧版本还在fvm的仓库里存着:

# 查看本机已安装的可用版本 fvm list # 项目重新绑定旧版本 fvm use 3.19.6 # 重新拉取依赖 fvm flutter pub get

这个过程不需要删除、不需要重新下载,切换和依赖拉取加起来不超过两分钟。我实际用下来,回退之后唯一需要留意的是Android的Gradle缓存在版本切换后偶尔会重建一次,首次编译会稍慢,多等一会儿就能看到正常的构建输出。

4.3 安装并切换一个全新的"试验版本"

如果你只是想体验一下新版本Flutter的特性,又不想影响当前正在进行的项目,可以先把新版本装进fvm,然后单独建一个目录跑一下demo验证效果,验证完直接删掉这个目录就可以了,当前项目完全不受影响。fvm隔离存储的机制让这种"平行试验"变得特别轻松。

5. IDE与工具链的版本联动配置

命令行切好版本只是第一步,IDE里如果用错版本照样寸步难行。VS Code和Android Studio各自都要做对应的联动设置。

5.1 VS Code的配置

VS Code打开Flutter项目后,默认使用flutter全局命令对应的SDK。要让它使用fvm管理的项目特定版本,在项目根目录的.vscode/settings.json里加上一行:

{ "dart.flutterSdkPath": ".fvm/flutter_sdk" }

这里的关键是路径得指向项目根目录下的.fvm软链接。fvm在fvm use阶段已经帮我们建好了链接关系,所以这里直接用相对路径就行。设置完之后,重启VS Code,状态栏右下角的Flutter版本应该显示为当前项目绑定版本。我在多版本切换测试时发现,如果VS Code不重启,有些版本相关的提示(比如LSP的SDK版本信息)不会立即刷新,重启一下最稳妥。

5.2 Android Studio的配置

Android Studio的配置稍微绕一点。打开File -> Settings -> Languages & Frameworks -> Flutter,把Flutter SDK path改成fvm的SDK实际路径。注意这里不能用项目根目录的相对路径,需要指向真实的SDK存储路径,因为Android Studio的配置是全局的,不像VS Code按项目读取。

如果你用fvm global 3.24.0设置了全局版本,可以把Android Studio的Flutter SDK路径指到对应版本的实际路径,比如D:\dev\fvm\versions\3.24.0。但如果经常在多个项目间切换,这种方式就不靠谱了,因为全局版本一变,Android Studio里配置的路径就失效,需要频繁去改设置项。

我的做法是:Android Studio的Flutter SDK路径保持指向一个固定的全局稳定版本,日常在这个IDE里只做该版本兼容范围内的开发。需要用其他版本做验证时切回VS Code操作,两个IDE各司其职。

提示:VS Code的.fvm/flutterSdkPath配置在fvm 2.x之后的版本推荐直接写成.fvm/flutter_sdk,旧的写法可能不兼容新版fvm,遇到配置不生效可以检查下这个字段的写法。

5.3 终端环境的PATH联动

fvm global切换版本之后,当前已打开的终端窗口中的flutter命令不会立即切换,因为PATH变量在窗口开启时就已经确定了。我看到不少人在这一步以为fvm坏了,其实只需要关掉终端重开一个新的即可。

另外,fvm会在%USERPROFILE%\fvm\default路径下维护一个指向当前全局版本SDK的软链接。即使你不清楚fvm内部逻辑,只要确保这个软链接存在且指向正确版本,flutter命令就能正常工作。

6. Windows下使用fvm的坑:版本缓存、镜像源与Gradle冲突

fvm在Windows上整体很稳定,但使用时间长了你总会碰到几个奇怪的小问题,这里把我踩过的坑集中说一下。

6.1 国内网络下载Flutter SDK慢或失败

fvm安装版本时是从Flutter官方存储下载SDK,国内网络环境下载大文件经常超时。这种问题不需要折腾fvm本身,设置一下镜像环境变量即可让fvm自动走国内镜像:

# 设置Flutter镜像源 setx FLUTTER_STORAGE_BASE_URL "https://storage.flutter-io.cn" setx PUB_HOSTED_URL "https://pub.flutter-io.cn"

设置完镜像后重新打开终端,再执行fvm install 3.19.6,速度会有肉眼可见的提升。需要注意的是这两个变量最好在安装Flutter SDK之前设置,因为首次安装时fvm需要下载SDK和Dart SDK依赖,这两个下载源是对应的。如果已经装完再设变量,对已装好的版本没有影响,只对后续新版本有效。

6.2 fvm缓存目录占用过多磁盘空间

fvm把每个版本的Flutter SDK完整存放在独立目录下,版本装多了磁盘占用相当可观。我自己观察过,每个版本的SDK加Dart SDK,大约占用2.5GB到3.5GB不等,装8个版本就是差不多30GB。

清理不需要的版本直接这样操作:

fvm remove 3.7.12

它会删除对应的SDK目录并清理引用记录。我建议定期用fvm list看一下本机装了哪些版本,只保留最近一两个稳定版和项目实际在用的版本。不过注意,执行fvm remove之前确认一下没有项目还在引用这个版本,否则下次fvm use不得不再重新装一遍。

6.3 Gradle构建缓存与Flutter版本的耦合问题

所有Flutter项目在构建Android端时都会依赖本地的Gradle缓存,而不同Flutter版本默认生成的Gradle版本不一样。切换版本后,第一次构建可能会自动下载对应版本的Gradle wrapper,这又是个不小的下载量。

我的建议是:在项目正式升级Flutter版本之后,执行一次flutter clean,清除旧的构建产物,然后重新fvm flutter pub get和构建。虽然首次构建时间会变长,但能避免很多来源不明的奇怪报错。

7. 团队协作场景下fvm的最佳实践配置

fvm不只是个人开发利器,在团队协作中价值更大。我团队现在就全员使用fvm,统一了项目版本管理流程,基本消除了"我本地能编译你那边报错"这种问题。

7.1 用.fvmrc文件统一团队版本

所有项目根目录都提交.fvmrc文件,里面写清楚该项目使用的Flutter版本。新人加入时,按照项目README指引执行两条命令就行:

fvm install fvm use

fvm install不带参数时,会自动读取当前项目.fvmrc中声明的版本并安装;fvm use会自动切换。全流程不需要知道具体版本号是多少。

7.2 CI/CD流水线中的fvm集成

我们的CI流水线(GitHub Actions和Jenkins都有)在构建步骤里增加了fvm环境准备:

steps: - uses: actions/checkout@v4 - name: Setup fvm run: | dart pub global activate fvm fvm install fvm use - name: Build run: | fvm flutter pub get fvm flutter build apk --release

这样CI环境和本地环境用的是完全相同的Flutter版本,不再出现"本地构建正常但CI挂了"这类问题。

7.3 版本升级的团队协作流程

我们团队升级Flutter版本不是某个人自己升级完就完事,而是有个不太严格的流程:

  1. 先在个人分支上执行fvm use 新版本号
  2. 跑一遍完整的analyzetestbuild,解决掉当前代码的所有兼容问题
  3. 提交一个只更新.fvmrc和修复兼容性代码的PR
  4. 团队其他成员拉取代码后执行fvm use自动切到新版本,然后跑各自的模块

整个过程前后不超过十分钟,没有一个人需要手动去装SDK或者改PATH。对比一下以前没有fvm的时候,一次版本升级经常要折腾整个组一两天,效率提升非常明显。

8. 我常用的fvm高频命令速查表

用熟之后你会发现真正高频的命令也就十条以内,整理成速查表方便查:

命令功能使用频率
fvm install 版本号安装指定版本Flutter SDK
fvm use 版本号绑定项目版本
fvm global 版本号设置全局默认版本
fvm list查看本机已安装版本
fvm remove 版本号删除某个版本
fvm flutter 命令用项目版本执行Flutter命令极高
fvm dart 命令用项目版本执行Dart命令
fvm doctor环境自检
fvm --version查看fvm自身版本

关于fvm自身的升级,直接fvm工具本身走包管理器更新,简单方便。fvm升级不影响已安装的Flutter版本,这点不用担心。

最后分享一个实际使用中的个人习惯:每创建一个新项目,第一件事就是fvm use绑定版本,而不是等跑起来再处理。用fvm之后,项目里的README还会附上一行fvm install && fvm use作为环境准备命令。新环境准备时间从以前的一两个小时缩短到十几分钟,回想当年手动下载SDK、解压、配置PATH的折腾过程,现在是真的回不去了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询