Flutter Android 工程结构及应用层编译源码深入分析

本文详细探讨了Flutter Android项目的构建流程,包括从Project中读取配置属性、生成编译任务、处理ABI变体、打包SO库、合并assets以及Flutter SDK中的脚本执行。通过分析`addFlutterDeps`方法,揭示了Flutter如何编译代码、打包SO库到`libs.jar`,以及assets的合并过程。同时,文章还介绍了Flutter SDK的内部结构和执行流程,强调了`flutter`命令本质上是dart命令的包装,执行的命令最终指向`flutter_tools.dart`的main方法。
摘要由CSDN通过智能技术生成

if (project.hasProperty(‘extra-gen-snapshot-options’)) {

extraGenSnapshotOptionsValue = project.property(‘extra-gen-snapshot-options’)

}

String splitDebugInfoValue = null

if (project.hasProperty(‘split-debug-info’)) {

splitDebugInfoValue = project.property(‘split-debug-info’)

}

Boolean dartObfuscationValue = false

if (project.hasProperty(‘dart-obfuscation’)) {

dartObfuscationValue = project.property(‘dart-obfuscation’).toBoolean();

}

Boolean treeShakeIconsOptionsValue = false

if (project.hasProperty(‘tree-shake-icons’)) {

treeShakeIconsOptionsValue = project.property(‘tree-shake-icons’).toBoolean()

}

String dartDefinesValue = null

if (project.hasProperty(‘dart-defines’)) {

dartDefinesValue = project.property(‘dart-defines’)

}

String bundleSkSLPathValue;

if (project.hasProperty(‘bundle-sksl-path’)) {

bundleSkSLPathValue = project.property(‘bundle-sksl-path’)

}

String performanceMeasurementFileValue;

if (project.hasProperty(‘performance-measurement-file’)) {

performanceMeasurementFileValue = project.property(‘performance-measurement-file’)

}

String codeSizeDirectoryValue;

if (project.hasProperty(‘code-size-directory’)) {

codeSizeDirectoryValue = project.property(‘code-size-directory’)

}

Boolean deferredComponentsValue = false

if (project.hasProperty(‘deferred-components’)) {

deferredComponentsValue = project.property(‘deferred-components’).toBoolean()

}

Boolean validateDeferredComponentsValue = true

if (project.hasProperty(‘validate-deferred-components’)) {

validateDeferredComponentsValue = project.property(‘validate-deferred-components’).toBoolean()

}

def targetPlatforms = getTargetPlatforms()

}

可以看到,addFlutterTasks 方法的第一部分比较简单,基本都是从 Project 中读取各自配置属性供后续步骤使用。所以我们接着继续看 addFlutterTasks 这个方法步骤 1 之后的部分:

private void addFlutterTasks(Project project) {

//一堆属性获取与赋值操作

//…

//1、定义 addFlutterDeps 箭头函数,参数variant为标准构建对应的构建类型

def addFlutterDeps = { variant ->

if (shouldSplitPerAbi()) {

//2、常规操作:如果是构建多个变体apk模式就处理vc问题

variant.outputs.each { output ->

//由于GP商店不允许同一个应用的多个APK全都具有相同的版本信息,因此在上传到Play商店之前,您需要确保每个APK都有自己唯一的versionCode,这里就是做这个事情的。

//具体可以看官方文档 https://developer.android.com/studio/build/configure-apk-splits

def abiVersionCode = ABI_VERSION.get(output.getFilter(OutputFile.ABI))

if (abiVersionCode != null) {

output.versionCodeOverride =

abiVersionCode * 1000 + variant.versionCode

}

}

}

//3、获取编译类型,variantBuildMode值为debug、profile、release之一

String variantBuildMode = buildModeFor(variant.buildType)

//4、依据参数生成一个task名字,譬如这里的compileFlutterBuildDebug、compileFlutterBuildProfile、compileFlutterBuildRelease

String taskName = toCammelCase([“compile”, FLUTTER_BUILD_PREFIX, variant.name])

//5、给当前project创建compileFlutterBuildDebug、compileFlutterBuildProfile、compileFlutterBuildRelease Task

//实现为FlutterTask,主要用来编译Flutter代码,这个task稍后单独分析

FlutterTask compileTask = project.tasks.create(name: taskName, type: FlutterTask) {

//各种task属性赋值操作,基本都来自上面的属性获取或者匹配分析

flutterRoot this.flutterRoot

flutterExecutable this.flutterExecutable

buildMode variantBuildMode

localEngine this.localEngine

localEngineSrcPath this.localEngineSrcPath

//默认dart入口lib/main.dart、可以通过target属性自定义指向

targetPath getFlutterTarget()

verbose isVerbose()

fastStart isFastStart()

fileSystemRoots fileSystemRootsValue

fileSystemScheme fileSystemSchemeValue

trackWidgetCreation trackWidgetCreationValue

targetPlatformValues = targetPlatforms

sourceDir getFlutterSourceDirectory()

//学到一个小技能,原来中间API是AndroidProject.FD_INTERMEDIATES,这也是flutter中间产物目录

intermediateDir project.file(“ p r o j e c t . b u i l d D i r / {project.buildDir}/ project.buildDir/{AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/”)

extraFrontEndOptions extraFrontEndOptionsValue

extraGenSnapshotOptions extraGenSnapshotOptionsValue

splitDebugInfo splitDebugInfoValue

treeShakeIcons treeShakeIconsOptionsValue

dartObfuscation dartObfuscationValue

dartDefines dartDefinesValue

bundleSkSLPath bundleSkSLPathValue

performanceMeasurementFile performanceMeasurementFileValue

codeSizeDirectory codeSizeDirectoryValue

deferredComponents deferredComponentsValue

validateDeferredComponents validateDeferredComponentsValue

//最后做一波权限相关处理

doLast {

project.exec {

if (Os.isFamily(Os.FAMILY_WINDOWS)) {

commandLine(‘cmd’, ‘/c’, “attrib -r ${assetsDirectory}/* /s”)

} else {

commandLine(‘chmod’, ‘-R’, ‘u+w’, assetsDirectory)

}

}

}

}

//项目构建中间产物的文件,也就是根目录下build/intermediates/flutter/debug/libs.jar文件

File libJar = project.file(“ p r o j e c t . b u i l d D i r / {project.buildDir}/ project.buildDir/{AndroidProject.FD_INTERMEDIATES}/flutter/${variant.name}/libs.jar”)

//6、创建packLibsFlutterBuildProfile、packLibsFlutterBuildDebug、packLibsFlutterBuildRelease任务,主要是产物的复制挪位置操作,Jar 类型的 task

//作用就是把build/intermediates/flutter/debug/下依据abi生成的app.so通过jar命令打包成build/intermediates/flutter/debug/libs.jar

Task packFlutterAppAotTask = project.tasks.create(name: “packLibs F L U T T E R B U I L D P R E F I X {FLUTTER_BUILD_PREFIX} FLUTTERBUILDPREFIX{variant.name.capitalize()}”, type: Jar) {

//目标路径为build/intermediates/flutter/debug目录

destinationDir libJar.parentFile

//文件名为libs.jar

archiveName libJar.name

//依赖前面步骤5定义的compileFlutterBuildDebug,也就是说,这个task基本作用是产物处理

dependsOn compileTask

//targetPlatforms取值为android-arm、android-arm64、android-x86、android-x64

targetPlatforms.each { targetPlatform ->

//abi取值为armeabi-v7a、arm64-v8a、x86、x86_64

String abi = PLATFORM_ARCH_MAP[targetPlatform]

//数据来源来自步骤5的compileFlutterBuildDebug任务中间产物目录

//即把build/intermediates/flutter/debug/下依据abi生成的app.so通过jar命令打包成一个build/intermediates/flutter/debug/libs.jar文件

from(“ c o m p i l e T a s k . i n t e r m e d i a t e D i r / {compileTask.intermediateDir}/ compi

  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值