通过源码分析Flutter项目创建过程
Flutter 项目种类
enum FlutterProjectType {
app, // Flutter项目,主体是Flutter。
module, // 主体是原生项目,用于在原生iOS、Android项目中添加Flutter模块,用于原生与Flutter混合开发。
package, // 纯Flutter模块,不需要原生代码实现
plugin, // 原生模块,在Flutter项目引入插件来实现原生的功能。
}
本文主要分析 app
类型的创建过程,其他类型的原理类似
源码目录
打开 flutter/packages/flutter_tools/lib/src/commands/create.dart
文件
可以看到类名是
CreateCommand
, runCommand()
函数是类的主函数
runCommand 主要流程
Future<FlutterCommandResult> runCommand() async {
final FlutterProjectType template = _getProjectType(projectDir); // 项目类型, app/module....
final List<String> platforms = stringsArg('platforms'); // 支持系统平台: ios/android/web...
final String organization = await getOrganization(); // 项目组织名称
final bool overwrite = boolArgDeprecated('overwrite'); // 是否覆盖已经存在的文件
final String dartSdk = globals.cache.dartSdkBuild; // dart版本
final bool includeIos; // 是否包含iOS项目
final bool includeAndroid; // 是否包含Android项目
final bool includeWeb; // 是否包含Web项目
final bool includeLinux; // 是否包含Linux项目
final bool includeMacos; // 是否包含MacOS项目
final bool includeWindows; // 是否包含Windows项目
if (template == FlutterProjectType.module) { // module 只支持Android和iOS平台
includeIos = true;
includeAndroid = true;
includeWeb = false;
includeLinux = false;
includeMacos = false;
includeWindows = false;
} else {
includeIos = featureFlags.isIOSEnabled && platforms.contains('ios');
includeAndroid =
featureFlags.isAndroidEnabled && platforms.contains('android');
includeWeb = featureFlags.isWebEnabled && platforms.contains('web');
includeLinux = featureFlags.isLinuxEnabled && platforms.contains('linux');
includeMacos = featureFlags.isMacOSEnabled && platforms.contains('macos');
includeWindows =
featureFlags.isWindowsEnabled && platforms.contains('windows');
}
String? developmentTeam; // 获取iOS 的开发Team
if (includeIos) {
developmentTeam = await getCodeSigningIdentityDevelopmentTeam(
processManager: globals.processManager,
platform: globals.platform,
logger: globals.logger,
config: globals.config,
terminal: globals.terminal,
);
}
// Flutter要求项目名称小写驼峰命名
final String titleCaseProjectName = snakeCaseToTitleCase(projectName);
// 项目信息Map
final Map<String, Object?> templateContext = createTemplateContext(
organization: organization, // 项目组织
projectName: projectName, // 项目名称
titleCaseProjectName: titleCaseProjectName,
projectDescription: stringArgDeprecated('description'), // 项目描述
flutterRoot: flutterRoot, // flutter根目录
androidLanguage: stringArgDeprecated('android-language'), // Android 使用的语言 Java/Kotlin
iosLanguage: stringArgDeprecated('ios-language'), // iOS 使用的语言 OC/Swift
iosDevelopmentTeam: developmentTeam, // iOS 开发team 名称
ios: includeIos, // 是否包含iOS项目
android: includeAndroid, // 是否包含Android项目
web: includeWeb, // 是否包含 Web 项目
linux: includeLinux, // 是否包含 Linux 项目
macos: includeMacos, // 是否包含 MacOS项目
windows: includeWindows, // 是否包含 Windows 项目
dartSdkVersionBounds: "'>=$dartSdk <3.0.0'", // dart版本
implementationTests: boolArgDeprecated('implementation-tests'),
agpVersion: gradle.templateAndroidGradlePluginVersion,
kotlinVersion: gradle.templateKotlinGradlePluginVersion, // kotlin版本
gradleVersion: gradle.templateDefaultGradleVersion, // gradle版本
);
final bool creatingNewProject =
!projectDir.existsSync() || projectDir.listSync().isEmpty;
final Directory relativeDir = globals.fs.directory(projectDirPath);
int generatedFileCount = 0;
PubContext pubContext = PubContext.create;
switch (template) {
case FlutterProjectType.app:
generatedFileCount += await generateApp( // generateApp方法去生成 App
<String>['app', 'app_test_widget'],
relativeDir,
templateContext,
overwrite: overwrite,
printStatusWhenWriting: !creatingNewProject,
projectType: template,
);
pubContext = PubContext.create;
break;
case FlutterProjectType.module:
generatedFileCount += await _generateModule(
relativeDir,
templateContext,
overwrite: overwrite,
printStatusWhenWriting: !creatingNewProject,
);
pubContext = PubContext.create;
break;
}
if (boolArgDeprecated('pub')) { // 更新Flutter pub依赖
final FlutterProject project = FlutterProject.fromDirectory(relativeDir);
await pub.get(
context: pubContext,
project: project,
offline: boolArgDeprecated('offline'),
);
}
return FlutterCommandResult.success();
}
templates(模版)目录
flutter/packages/flutter_tools/templates
中存放各个projectType的模版项目和文件
- android + android-java/android-kotlin
- ios + ios-objc/ios-swift
generaeApp()
从 flutter/packages/flutter_tools/templates
中拷贝项目和文件到目标directory
Future<int> generateApp(
List<String> templateNames,
Directory directory,
Map<String, Object?> templateContext, {
bool overwrite = false,
bool pluginExampleApp = false,
bool printStatusWhenWriting = true,
bool generateMetadata = true,
FlutterProjectType? projectType,
}) async {
int generatedCount = 0;
/// 拷贝 'app', 'app_test_widget', 'app_shared'三个目录文件
generatedCount += await renderMerged(
<String>[...templateNames, 'app_shared'],
directory,
templateContext,
overwrite: overwrite,
printStatusWhenWriting: printStatusWhenWriting,
);
if (templateContext['android'] == true) { // 如果包含Android工程,则缓存Gradle
generatedCount += _injectGradleWrapper(project);
}
if (androidPlatform) { // android 平台需要额外更新属性
gradle.updateLocalProperties(project: project, requireAndroidSdk: false);
}
// 返回生成了多少个文件
return generatedCount;
}
创建成功
转载自:https://juejin.cn/post/7240081817721864251