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

================================================================================

下面我们从纯 Flutter 项目的 app 编译安卓端 apk 流程说起。

[](()settings.gradle 源码流程分析


既然是安卓的编译流程,那就先从android/settings.gradle看起,如下:

// 当前 app module

include ‘:app’

/**

  • 1、读取android/local.properties文件内容

  • 2、获取flutter.sdk的值,也就是你本地flutter SDK安装目录

  • 3、gradle 脚本常规操作 apply flutter SDK路径下/packages/flutter_tools/gradle/app_plugin_loader.gradle文件

*/

def localPropertiesFile = new File(rootProject.projectDir, “local.properties”)

def properties = new Properties()

assert localPropertiesFile.exists()

localPropertiesFile.withReader(“UTF-8”) { reader -> properties.load(reader) }

def flutterSdkPath = properties.getProperty(“flutter.sdk”)

assert flutterSdkPath != null, “flutter.sdk not set in local.properties”

apply from: “$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle”

通过上面步骤我们可以将目光转向你 Flutter SDK 安装目录下的/packages/flutter_tools/gradle/app_plugin_loader.gradle文件,内容如下:

import groovy.json.JsonSlurper

//得到自己新建的 flutter 项目的根路径,因为已经被自己新建的 project apply,所以这里是项目根路径哦

def flutterProjectRoot = rootProject.projectDir.parentFile

//获取自己项目根路径下的.flutter-plugins-dependencies json配置文件

// Note: if this logic is changed, also change the logic in module_plugin_loader.gradle.

def pluginsFile = new File(flutterProjectRoot, ‘.flutter-plugins-dependencies’)

if (!pluginsFile.exists()) {

return

}

/**

  • 1、通过groovy的JsonSlurper解析json文件内容。

  • 2、简单校验json内容字段的类型合法性。

  • 3、把安卓平台依赖的Flutter plugins全部自动include进来

*/

def object = new JsonSlurper().parseText(pluginsFile.text)

assert object instanceof Map

assert object.plugins instanceof Map

assert object.plugins.android instanceof List

// Includes the Flutter plugins that support the Android platform.

object.plugins.android.each { androidPlugin ->

assert androidPlugin.name instanceof String

assert androidPlugin.path instanceof String

def pluginDirectory = new File(androidPlugin.path, ‘android’)

assert pluginDirectory.exists()

include “{androidPlugin.name}”

project(“{androidPlugin.name}”).projectDir = pluginDirectory

}

上面的 gradle 脚本很简单,大家看注释即可。为了直观说明问题,这里新建了一个典型 demo 项目,然后其pubspec.yaml文件依赖配置如下:

dependencies:

flutter:

sdk: flutter

dio: ^4.0.0 #来自pub.dev仓库的Flutter Package包

webview_flutter: ^2.0.10 #来自pub.dev仓库的Flutter Plugin包

f_package: #来自自己本地新建的Flutter Package包

path: ./…/f_package

f_plugin: #来自自己本地新建的Flutter Plugin包

path: ./…/f_plugin

接着我们看看这个项目根路径的.flutter-plugins-dependencies文件,如下:

{

“info”:“This is a generated file; do not edit or check into version control.”,

“plugins”:{

“ios”:[

{“name”:“f_plugin”,“path”:“E:\\f_plugin\\”,“dependencies”:[]},

{“name”:“webview_flutter”,“path”:“D:\\software\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\webview_flutter-2.0.10\\”,“dependencies”:[]}

],

“android”:[

{“name”:“f_plugin”,“path”:“E:\\f_plugin\\”,“dependencies”:[]},

{“name”:“webview_flutter”,“path”:“D:\\software\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\webview_flutter-2.0.10\\”,“dependencies”:[]}

],

“macos”:[],

“linux”:[],

“windows”:[],

“web”:[

{“name”:“f_plugin”,“path”:“E:\\f_plugin\\”,“dependencies”:[]}

]

},

“dependencyGraph”:[

{“name”:“f_plugin”,“dependencies”:[]},

{“name”:“webview_flutter”,“dependencies”:[]}

],

“date_created”:“202x-0x-15 21:41:39.225336”,

“version”:“2.2.3”

}

这时候我们回过头去看自己项目android/settings.gradle,在 Gradle 生命周期的初始化阶段(即解析settings.gradle),我们项目的settings.gradle经过apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"处理后自动变成如下伪代码:

include ‘:app’

// 自动通过匹配依赖然后app_plugin_loader.gradle解析生成

//include “{androidPlugin.name}”

//project(“{androidPlugin.name}”).projectDir = pluginDirectory

include “:f_plugin”

project(“:f_plugin”).projectDir = new File(“E:\\f_plugin\\”, ‘android’)

include “:webview_flutter”

project(“:webview_flutter”).projectDir = new File(“D:\\software\\flutter\\flutter\\.pub-cache\\hosted\\pub.dartlang.org\\webview_flutter-2.0.10\\”, ‘android’)

咋说!是不是一下就恍然大悟了,其实就是“约定大于配置”的软件工程原则,你只管按照规则摆放,本质最后都是我们平时标准 Android 项目那样。

[](()build.gradle源码流程分析


先看项目 android 下根目录的build.gradle,如下:

//…省略无关紧要的常见配置

// 看到了吧,他将所有 android 依赖的构建产物挪到了根目录下的 build 中,所以产物都在那儿

rootProject.buildDir = ‘…/build’

subprojects {

project.buildDir = “ r o o t P r o j e c t . b u i l d D i r / {rootProject.buildDir}/ rootProject.buildDir/{project.name}”

project.evaluationDependsOn(‘:app’) //运行其他配置之前,先运行app依赖

}

接着我们看看 app 模块下的build.gradle,如下:

/**

  • 1、读取local.properties配置信息。

  • 2、获取flutter.sdk路径。

  • 3、获取flutter.versionCode值,此值在编译时自动从pubspec.yaml中读取赋值,所以修改版本号请修改yaml。

  • 4、获取flutter.versionName值,此值在编译时自动从pubspec.yaml中读取赋值,所以修改版本号请修改yaml。

*/

def localProperties = new Properties()

def

你可能感兴趣的:(Android,经验分享,面试)