DEVLOG 9.22 Gradle 笔记(1)Gradle重要概念扫盲
构建生命周期
初始化 - 配置 - 执行
初始化阶段:
初始化阶段Gradle会根据根目录下面的settings.gradle构建Settings对象,settings.gradle会决定有哪些模块参与构建。构建工具会根据每一个build.gradle构建Project对象。根目录的build
.gradle可以理解为最顶层的Project,每一个模块中的Project可以通过rootProject访问根目录的Project对象。构建工具之后会根据Settings配置Project
配置阶段:
配置阶段Gradle会分析每一个Project的依赖关系。
举华师匣子2.0为例,华师匣子2.0中配置了很多不同的module,这些module的初衷是为了让业务分离,让开发者更注重于开发主要业务。如果存在不同的模块的话,维护起来会更加方便,但是这个解耦并不完全,因为我们并没有将不同的功能分成不同的模块。不同的模块之前的UI跳转需要使用Arouter实现,我们没有这样分,所以也没有真正的使用Arouter。

执行阶段:
执行阶段会执行Task。会按照Task的依赖顺序执行。
Project
build.gradle中使用的函数 DSL块不外乎都是Project以及它继承而来的方法。

application build.gradle 和 app build
application层级的build.gradle是最顶级的Project,里面包括了子Project,也就是app的build.gradle。当Gradle启动的时候,会先启动settings.gradle,生成Settings对象,然后再按照这个对象的要求配置build.gradle,include的相关代码就写在settings.gradle中。

子Project中定义的Task也可以被顶级Project访问到。假设我在app module中定义了这两个Task(hello 和 subTask)
使用如下命令可以在打印中找到这两个Task是属于app的:

每一个build.gradle 都代表着一个project,每个project都有若干个task。Task表示Gradle的一个原子性操作。
Task
Task表示一系列的Action ,因此可以使用doFirst或者doLast向Task中添加Action对象。Action是一个接口,使用的感觉其实上就是一个闭包
Task的创建
在build.gradle中可以获取当前的Project的实例,并且可以通过tasks获取TaskContainer对象,然后就可以将新的Task加入Project
2. Task的依赖
一个Task又通过若干个Action组成。Gradle中原本的Task的执行顺序是不确定的,可以通过使用dependsOn指定Task的依赖顺序。
3. Task和增量构建
Gradle会缓存Task每次的运行结果,在下次运行时,检查输出结果有无变更,如果没有变更就回跳过这次运行。如果输入没有变化输出也不会发生变化。

ext命名空间
ext其实ExtensionAware的一个特殊属性
我们可以在顶级的build.gradle的同级目录下定义一个config.build,里面使用ext定义我们全局所需要的各种常量:
但是这个config.gradle,需要在build.gradle中apply:
这实际上调用的是PluginAware的方法:
于是我们可以在顶级的build.gradle和app模块的build.gradle中访问到:

我们可以使用Extension给一些可以配置的插件传值,如果不使用managed properties,我们也可以使用这样的形式:
这里不写getter和setter也是可以的
managed properties:
Gradle能够允许用户声明一个属性为抽象的getter或者是一个抽象的属性,然后Gradle会自动提供这些属性的实现:https://docs.gradle.org/current/userguide/custom_gradle_types.html#managed_types
Mutable properties:
声明一个mutable managed property,需要给Property<T>提供一个抽象的getter。这里的T可以是任意的序列化类型或者是一个fully Gradle Managed type。对于这种属性,一定不可以声明任何的setter方法。这个东西有点像kotlin自动生成的getter和setter:
这里的@Input和@TaskAction注解都是一个mark的作用。TaskAction表示这个方法会被标记成一个action,在Task执行时被运行。
这里和上面直接写一个类然后设置值的方式好像没有本质上的不同,但是这里的getUri(getter)可以被转化成一个类似于Kotlin中的字段同时有了getter和setter的功能。
Read-only managed properties
使用只读的properties需要给Provider<T>加上getter方法,这个方法的实现中必须给出这个结果的推导方式:
Read-only managed nested properties
对于一个嵌套类型的传值。在这种情况下,用户不需要写任何的setter,因为Gradle会自动实现,并且Gradle会将值传给嵌套类型内部的properties。如果当前的property被声明为一个read-only managed nested property,这个property的getter 方法必须是抽象的并且public或者protected可见性,同时这个getter方法还需要被注解为@Nested:
但是这里我还有点没有搞明白,这个Resources应该如何传值呢?
Managed Types
managed type是一个抽象类,或者接口。这个类中没有任何字段,并且这个类中的所有属性都是被managed(应该是指通过Gradle生成的方法处理?)比如我们上面的Resources
Java bean Properties
使用Java Bean风格的Property,这种类型中没有Property<T>和Provider<T>,但是使用了实现了的getter 和 setter(常用的Java Bean中getter setter 都被手写写好了)。这种方式在Gradle中是不被提倡的。

Extension
通过Project获取ExtensionContainer,初始化新的Extension并且存入ExtensionContainer中。
类似于ext,可以直接通过project获取:
同样也可以使用managed properties:
NamedDomainObjectContainer
我们定义的buildTypes就是领域对象容器。通过指定不同的buildTypes的名称release 和debug可以设置不同的参数。这也是一个extension,所以内部的release和debug的配置是BuildType对象通过ExtensionContainer#create构建出来的
参考文章:
https://juejin.cn/post/6844903838290296846
https://www.jianshu.com/p/207c9f6f68c2