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

本文深入分析了Flutter Android项目的编译过程,从`local.properties`开始,详细解释了如何通过`app_plugin_loader.gradle`解析依赖并包含Flutter插件。还探讨了Gradle构建流程,包括构建目录设置、版本信息读取、Flutter SDK的应用以及如何将Flutter插件编译产物整合到Android项目中。最后,介绍了`flutter.gradle`中关键任务的实现,如编译Flutter代码、打包SO库和处理assets资源。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

下面我们从纯 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 = “rootProject.buildDir/{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 localPropertiesFile = rootProject.file(‘local.properties’)

if (localPropertiesFile.exists()) {

localPropertiesFile.withReader(‘UTF-8’) { reader -&g

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值