Flutter环境搭建以及Flutter命令的执行过程

1,530 阅读5分钟
Flutter开发环境的搭建很简单,可以参考官方文档:
Flutter英文官网:flutter.dev/docs/get-st…

一、Flutter环境搭建

先简单介绍一下Flutter开发环境的搭建
  1. 下载最新版本的Zip安装包,比如storage.googleapis.com/flutter_inf…
  2. 解压压缩包到本地目录,比如~/dev_tools/flutter
  3. 将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是直接下发源码仓库,构建工具直接从源码生成,这样对于一个正在不断迭代更新中的项目来说,可以提高开发效率,降低维护成本,值得借鉴。