Flutter开发环境的搭建很简单,可以参考官方文档:
Flutter中文网:flutterchina.club/setup-macos…
Flutter英文官网:flutter.dev/docs/get-st…
一、Flutter环境搭建
先简单介绍一下Flutter开发环境的搭建
- 下载最新版本的Zip安装包,比如storage.googleapis.com/flutter_inf…
- 解压压缩包到本地目录,比如~/dev_tools/flutter
- 将flutter工具添加到PATH中
export PATH=~/dev_tools/flutter:$PATH
二、Flutter的目录结构
2.1 Flutter目录
下面来看一下Flutter解压后的目录中都有什么
admindeMacBook-Pro:flutter szw$ ls -la
total 224
drwxr-xr-x@ 27 szw staff 918 11 15 20:12 .
drwxr-xr-x 7 szw staff 238 11 12 16:38 ..
-rw-r--r--@ 1 szw staff 8196 11 12 16:39 .DS_Store
-rw-r--r--@ 1 szw staff 26010 10 18 01:03 .cirrus.yml
-rw-r--r--@ 1 szw staff 362 10 18 01:03 .codecov.yml
drwxr-xr-x@ 15 szw staff 510 11 16 10:40 .git
-rw-r--r--@ 1 szw staff 516 10 18 01:03 .gitattributes
drwxr-xr-x@ 6 szw staff 204 10 18 01:03 .github
-rw-r--r-- 1 szw staff 1757 11 15 15:13 .gitignore
drwxr-xr-x@ 6 szw staff 204 10 18 01:08 .idea
drwxr-xr-x@ 8 szw staff 272 11 12 16:38 .pub-cache
-rw-r--r--@ 1 szw staff 1581 10 18 01:03 AUTHORS
-rw-r--r--@ 1 szw staff 481 10 18 01:03 CODEOWNERS
-rw-r--r--@ 1 szw staff 2625 10 18 01:03 CODE_OF_CONDUCT.md
-rw-r--r--@ 1 szw staff 3815 10 18 01:03 CONTRIBUTING.md
-rw-r--r--@ 1 szw staff 1520 10 18 01:03 LICENSE
-rw-r--r--@ 1 szw staff 1107 10 18 01:03 PATENT_GRANT
-rw-r--r--@ 1 szw staff 4297 10 18 01:03 README.md
-rw-r--r--@ 1 szw staff 8745 10 18 01:03 analysis_options.yaml
drwxr-xr-x@ 6 szw staff 204 11 14 10:52 bin
-rw-r--r--@ 1 szw staff 607 10 18 01:03 dartdoc_options.yaml
drwxr-xr-x@ 15 szw staff 510 10 18 01:03 dev
drwxr-xr-x@ 13 szw staff 442 10 18 01:03 examples
-rw-r--r--@ 1 szw staff 1741 10 18 01:03 flutter_console.bat
-rw-r--r--@ 1 szw staff 296 10 18 01:03 flutter_root.iml
drwxr-xr-x@ 12 szw staff 408 11 6 20:48 packages
-rw-r--r-- 1 szw staff 20 11 15 21:34 version
我们发现里面有.git目录,原来这是个git仓库!
2.2 Flutter分支
我们看一下它的分支
admindeMacBook-Pro:flutter szw$ git branch
* stable
原来我们在stable分支。
再看下远程分支有哪些
admindeMacBook-Pro:flutter szw$ git branch -r
origin/HEAD -> origin/master
origin/Hixie-patch-1
origin/Hixie-patch-2
origin/Hixie-patch-3
origin/Hixie-patch-4
origin/beta
origin/dev
origin/generated_explicit_type
origin/hot_restart_lowercase_r
origin/master
origin/potato620-patch-1
origin/refactor
origin/revert-37962-show-search-app-bar-theme
origin/revert-38861-use_frame_timings
origin/revert-38922-text-docs
origin/revert-39627-master
origin/revert-40607-animationOverview
origin/revert-40634-goldenTriageBenchmark
origin/revert-40710-flutterGold
origin/revert-40726-roll_branch
origin/revert-41415-exposeimage
origin/revert-41780-fix_build
origin/revert-42236-add_rally_to_examples
origin/revert-43576-web_compiler
origin/revert-44315-roll_branch
origin/sjindel.elf
origin/stable
origin/v1.4.5-hotfixes
origin/v1.4.6-hotfixes
origin/v1.4.9-hotfixes
origin/v1.5.4-hotfixes
origin/v1.7.8-hotfixes
origin/v1.9.1-hotfixes
看一下现在的版本,一般每发一个release 版本都会打个tag,我们看一下最近的几个tag
admindeMacBook-Pro:flutter szw$ git describe --tags `git rev-list --tags --max-count=5`
v1.12.2
v1.12.1-23-g985da8313
v1.12.1-22-g001959941
v1.12.1-21-g66821916d
v1.12.1-20-gc0af77bf8
当前已经到了v1.12.2
三、Flutter命令的执行过程
3.1 flutter命令的路径
admindeMacBook-Pro:flutter szw$ which flutter
/Users/szw/dev_tools/flutter/bin/flutter
就是我们前面加入到PATH中的路径
3.2 flutter脚本的内容
#!/usr/bin/env bash
PROG_NAME="$(path_uri "$(follow_links "$BASH_SOURCE")")"
BIN_DIR="$(cd "${PROG_NAME%/*}" ; pwd -P)"
export FLUTTER_ROOT="$(cd "${BIN_DIR}/.." ; pwd -P)"
FLUTTER_TOOLS_DIR="$FLUTTER_ROOT/packages/flutter_tools"
SNAPSHOT_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot"
STAMP_PATH="$FLUTTER_ROOT/bin/cache/flutter_tools.stamp"
SCRIPT_PATH="$FLUTTER_TOOLS_DIR/bin/flutter_tools.dart"
DART_SDK_PATH="$FLUTTER_ROOT/bin/cache/dart-sdk"
DART="$DART_SDK_PATH/bin/dart"
PUB="$DART_SDK_PATH/bin/pub"
(upgrade_flutter) 3< "$PROG_NAME"
"$DART" --packages="$FLUTTER_TOOLS_DIR/.packages" $FLUTTER_TOOL_ARGS "$SNAPSHOT_PATH" "$@"
上面是flutter/bin/flutter文件中的内容(有删减),可以看出这是个脚本文件。
其中的主要流程为:
- 检查flutter_tool是否实现升级(upgrade_flutter)。
- 使用dart运行$FLUTTER_ROOT/bin/cache/flutter_tools.snapshot,同时把参数传给它。
.snapshot文件相当于java中的.jar文件,flutter_tools.snapshot这个文件便是在upgrade_flutter中生成的。
upgrade_flutter的流程如下:
从上面的流程我们可以看出,flutter命令根本上是用dart在执行packages/flutter_tools/bin/flutter_tools.dart
生成snapshot目的是为了提高运行效率。
3.3 flutter tools中的命令
flutter_tools是一个dart package,我们看一下packages/flutter_tools/bin/flutter_tools.dart的内容
import 'package:flutter_tools/executable.dart' as executable;
void main(List<String> args) {
executable.main(args);
}
调用了flutter_tools/executable.dart中的main方法。
executable.dart的路径为packages/flutter_tools/lib/executable.dart
Future<void> main(List<String> args) async {
final bool verbose = args.contains('-v') || args.contains('--verbose');
final bool doctor = (args.isNotEmpty && args.first == 'doctor') ||
(args.length == 2 && verbose && args.last == 'doctor');
final bool help = args.contains('-h') || args.contains('--help') ||
(args.isNotEmpty && args.first == 'help') || (args.length == 1 && verbose);
final bool muteCommandLogging = help || doctor;
final bool verboseHelp = help && verbose;
await runner.run(args, <FlutterCommand>[
AnalyzeCommand(verboseHelp: verboseHelp),
AssembleCommand(),
AttachCommand(verboseHelp: verboseHelp),
BuildCommand(verboseHelp: verboseHelp),
ChannelCommand(verboseHelp: verboseHelp),
CleanCommand(),
ConfigCommand(verboseHelp: verboseHelp),
CreateCommand(),
DaemonCommand(hidden: !verboseHelp),
DevicesCommand(),
DoctorCommand(verbose: verbose),
DriveCommand(),
EmulatorsCommand(),
FormatCommand(),
GenerateCommand(),
IdeConfigCommand(hidden: !verboseHelp),
InjectPluginsCommand(hidden: !verboseHelp),
InstallCommand(),
LogsCommand(),
MakeHostAppEditableCommand(),
PackagesCommand(),
PrecacheCommand(),
RunCommand(verboseHelp: verboseHelp),
ScreenshotCommand(),
ShellCompletionCommand(),
TestCommand(verboseHelp: verboseHelp),
TrainingCommand(),
UnpackCommand(),
UpdatePackagesCommand(hidden: !verboseHelp),
UpgradeCommand(),
VersionCommand(),
], verbose: verbose,
muteCommandLogging: muteCommandLogging,
verboseHelp: verboseHelp,
overrides: <Type, Generator>{
// The build runner instance is not supported in google3 because
// the build runner packages are not synced internally.
CodeGenerator: () => const BuildRunner(),
WebCompilationProxy: () => BuildRunnerWebCompilationProxy(),
// The web runner is not supported internally because it depends
// on dwds.
WebRunnerFactory: () => DwdsWebRunnerFactory(),
});
}
executable.dart继而根据命令行参数,将执行过程转交给了具体的Command。
比如,当我们在命令行里运行flutter build命令时,最终是由BuildCommand这个类来处理的。
其他的命令也类似,当我们想了解某个flutter命令的原理时,便可以去看对应Command的源码了。
四、总结
有些SDK通常是下发编译好的可执行,而Flutter是直接下发源码仓库,构建工具直接从源码生成,这样对于一个正在不断迭代更新中的项目来说,可以提高开发效率,降低维护成本,值得借鉴。