Flutter flutter.gradle分析

文章目录

所有的分析基于当前的 1.4.7 版本,flutter sdk 的版本更新可能会修改这个文件

1Flutter 1.4.7 • channel dev • https://github.com/flutter/flutter.git
2Framework • revision 1bfa2f2311 (3 days ago) • 2019-03-29 10:05:18 -0700
3Engine • revision c4d14a0071
4Tools • Dart 2.2.1 (build 2.2.1-dev.2.0 None)

这个文件是 sdk 中的 android 部分的配置文件文件,简单分析一下流程,以便于魔改或在项目中可以配置项目

gradle 使用的是 groovy 的语法,是一个 jvm 语言,在语法层级上兼容 Java 语法

换句话说 System.out.println("hello world"); 这样的方法是可用的

分析 flutter 项目

项目 android/app/build.gradle 文件中都有定义

 1def localProperties = new Properties()
 2def localPropertiesFile = rootProject.file('local.properties')
 3if (localPropertiesFile.exists()) {
 4    localPropertiesFile.withReader('UTF-8') { reader ->
 5        localProperties.load(reader)
 6    }
 7}
 8
 9def flutterRoot = localProperties.getProperty('flutter.sdk')
10if (flutterRoot == null) {
11    throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
12}
13
14def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
15if (flutterVersionCode == null) {
16    flutterVersionCode = '1'
17}
18
19def flutterVersionName = localProperties.getProperty('flutter.versionName')
20if (flutterVersionName == null) {
21    flutterVersionName = '1.0'
22}
23
24apply plugin: 'com.android.application'
25apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" // 这句代表了引入flutter.gradle到项目中,路径是

build.gradle 是 gradle 项目的主文件,关于 gradle 和相关说明可以自行搜索,这个体系很庞大,展开介绍不太现实

前面的基本都是 groovy 语法

def 是 groovy 中的关键字,可以简单理解为和 dart 中的 var 同义

读取 local.properties,然后在 properties 中查找 flutter 的 sdk 目录,如果没有就报错退出

然后是读取 properties 中定义的 versionCode 和 versionName

后面就是"引用" flutter.gradle 到项目中,通过这样的过程,flutter.gradle 的内容就被引入项目中了

flutter.gradle 的路径需要在 flutter sdk 目录下搜索 packages/flutter_tools/gradle/flutter.gradle

分析 flutter.gradle

开始是一些导包之类的相关代码

20190401132553.png

最后一行是一句关键的代码,引入插件FlutterPlugin,这个是告诉 gradle,我需要引入这个插件

这个插件就定义在这个文件内

20190401133009.png

查看主要的方法也就是 apply 方法,可以简单的理解为回调方法,处理整个项目

  1    @Override
  2    void apply(Project project) {
  3        // Add custom build types
  4        // 定义一些buildType
  5        project.android.buildTypes {
  6            profile {
  7                initWith debug //初始化参数来自于debug
  8                if (it.hasProperty('matchingFallbacks')) {
  9                    matchingFallbacks = ['debug', 'release']
 10                }
 11            }
 12            dynamicProfile {
 13                initWith debug
 14                if (it.hasProperty('matchingFallbacks')) {
 15                    matchingFallbacks = ['debug', 'release']
 16                }
 17            }
 18            dynamicRelease {
 19                initWith debug
 20                if (it.hasProperty('matchingFallbacks')) {
 21                    matchingFallbacks = ['debug', 'release']
 22                }
 23            }
 24        }
 25
 26        String flutterRootPath = resolveProperty(project, "flutter.sdk", System.env.FLUTTER_ROOT)
 27        // 查询flutter sdk的地址,如果没有定义,就查看FLUTTER_ROOT的环境变量,都没有就报错
 28        if (flutterRootPath == null) {
 29            throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file or with a FLUTTER_ROOT environment variable.")
 30        }
 31        flutterRoot = project.file(flutterRootPath)
 32        if (!flutterRoot.isDirectory()) { //不是文件夹说明sdk地址不对,也报错
 33            throw new GradleException("flutter.sdk must point to the Flutter SDK directory")
 34        }
 35
 36        // flutter的执行文件,windows执行bat,其他的执行flutter
 37        String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
 38        flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile();
 39
 40
 41        if (project.hasProperty('localEngineOut')) { // 这里可以理解为自定义engine,应该是用于engine开发或深度定制engine的情况, 普通的flutter使用者直接看else
 42            String engineOutPath = project.property('localEngineOut')
 43            File engineOut = project.file(engineOutPath)
 44            if (!engineOut.isDirectory()) {
 45                throw new GradleException('localEngineOut must point to a local engine build')
 46            }
 47            flutterJar = Paths.get(engineOut.absolutePath, "flutter.jar").toFile()
 48            if (!flutterJar.isFile()) {
 49                throw new GradleException('Local engine build does not contain flutter.jar')
 50            }
 51
 52            localEngine = engineOut.name
 53            localEngineSrcPath = engineOut.parentFile.parent
 54
 55            project.dependencies {
 56                if (project.getConfigurations().findByName("api")) {
 57                    api project.files(flutterJar)
 58                } else {
 59                    compile project.files(flutterJar)
 60                }
 61            }
 62        } else { //普通使用者
 63            Path baseEnginePath = Paths.get(flutterRoot.absolutePath, "bin", "cache", "artifacts", "engine")
 64            String targetArch = 'arm'
 65            if (project.hasProperty('target-platform') &&
 66                project.property('target-platform') == 'android-arm64') {
 67                    // 这里是判断类型,如果有target-platform属性,且属性是arm64,则认为目标类型是arm64,否则默认是arm
 68              targetArch = 'arm64'
 69            }
 70            debugFlutterJar = baseEnginePath.resolve("android-${targetArch}").resolve("flutter.jar").toFile()
 71            profileFlutterJar = baseEnginePath.resolve("android-${targetArch}-profile").resolve("flutter.jar").toFile()
 72            releaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-release").resolve("flutter.jar").toFile()
 73            dynamicProfileFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-profile").resolve("flutter.jar").toFile()
 74            dynamicReleaseFlutterJar = baseEnginePath.resolve("android-${targetArch}-dynamic-release").resolve("flutter.jar").toFile()
 75
 76            // 这些就是指定flutter.jar的类型
 77
 78            if (!debugFlutterJar.isFile()) {
 79                project.exec {
 80                    executable flutterExecutable.absolutePath
 81                    args "--suppress-analytics"
 82                    args "precache"
 83                }
 84                if (!debugFlutterJar.isFile()) { //类型不对就报错
 85                    throw new GradleException("Unable to find flutter.jar in SDK: ${debugFlutterJar}")
 86                }
 87            }
 88
 89            // Add x86/x86_64 native library. Debug mode only, for now.
 90            // 如果是debug的情况下,添加一个task用于copy x86/x86_64的so库到apk内
 91            flutterX86Jar = project.file("${project.buildDir}/${AndroidProject.FD_INTERMEDIATES}/flutter/flutter-x86.jar")
 92            Task flutterX86JarTask = project.tasks.create("${flutterBuildPrefix}X86Jar", Jar) {
 93                destinationDir flutterX86Jar.parentFile
 94                archiveName flutterX86Jar.name
 95                from("${flutterRoot}/bin/cache/artifacts/engine/android-x86/libflutter.so") {
 96                    into "lib/x86"
 97                }
 98                from("${flutterRoot}/bin/cache/artifacts/engine/android-x64/libflutter.so") {
 99                    into "lib/x86_64"
100                }
101            }
102            // Add flutter.jar dependencies to all <buildType>Api configurations, including custom ones
103            // added after applying the Flutter plugin.
104            project.android.buildTypes.each { addFlutterJarApiDependency(project, it, flutterX86JarTask) }
105            project.android.buildTypes.whenObjectAdded { addFlutterJarApiDependency(project, it, flutterX86JarTask) }
106        }
107
108        project.extensions.create("flutter", FlutterExtension)
109        project.afterEvaluate this.&addFlutterTask
110
111        // 这里是处理flutter插件, .flutter-plugins这个文件由flutter维护,来源于flutter项目中的pubspec.yaml
112        File pluginsFile = new File(project.projectDir.parentFile.parentFile, '.flutter-plugins')
113        Properties plugins = readPropertiesIfExist(pluginsFile)
114
115        plugins.each { name, _ ->
116            def pluginProject = project.rootProject.findProject(":$name")
117            if (pluginProject != null) {
118                // 这里两个循环就是将依赖需要的库引入当前项目内
119                project.dependencies {
120                    if (project.getConfigurations().findByName("implementation")) {
121                        implementation pluginProject
122                    } else {
123                        compile pluginProject
124                    }
125                }
126                pluginProject.afterEvaluate {
127                            pluginProject.android.buildTypes {
128                                profile {
129                                    initWith debug
130                                }
131                            }
132                }
133                pluginProject.afterEvaluate this.&addFlutterJarCompileOnlyDependency
134            } else {
135                project.logger.error("Plugin project :$name not found. Please update settings.gradle.")
136            }
137        }
138    }

我简单对于 apply 方法进行了分析加了一些注释

后记

很多东西需要对于 groovy 语法和 gradle 构建体系有所了解才能看懂,当然我也是萌新一枚,有错误或需要讨论可以留言

以上