02.Gradle生命周期
Gradle 生命周期
Gradle 生命周期阶段
Gradle 的执行分为三大阶段: Initialization
-> Configuration
-> Execution
阶段一: Initialization
初始化
Initialization
阶段主要目的是初始化构建, 它又分为两个子过程, 一个是执行 Init Script, 另一个是执行 Setting Script.
Init script (init.gradle.kts)
Init script 会读取全局脚本 (类似于系统 /etc/init.d
), 主要作用是初始化一些全局通用的属性, 例如获取 Gradle User Home 目录, Gradle version 等. 一般而言, 我们很少在 init script 中添加内容. Init script 执行顺序为:
$GRADLEUSERHOME/init.Gradle (. Kts)
$GRADLEUSERHOME/init. D/[*. Gradle (. Kts)]
由于 init script 主要任务是全局 Gradle 配置, 因此 Api 分为三大部分: 获取全局属性, 项目配置, 生命周期 Hook.
- Gradle 环境相关的属性:
gradleHomeDir/gradleUserHomeDir/gradleVersion
- 构建相关的全局属性: 我们从中可以获取
Gradle User Home
, current/project dir, 所有 system/project properties, 是否开启 scan, 是否 offline 等所有命令行参数 - rootProject 可以获取当前构建的根项目对象.
- taskGraph 可以获取当前构建的 task graph. 这个对象只有在收到
taskGraph.whenReady { … }
后才具有内容, 在此之前是个空壳对象.
Setting Script (setting.gradle[.kts]
)
Setting Script 指的是项目根目录下的 settings.gradle(.kts)
. 所有需要被构建的模块都需要在 setting script 中注册, 因此它的作用是描述 “ 当前构建所参与的模块 “, 本机任何位置的项目都可以通过 setting script 被引入到当前构建中.
setting script 承担了统筹所有模块的重任, 因此 api 主要是在操作所参与构建的模块以及管理构建过程需要的插件
Settings
settings.gradle 里面的配置和方法调用委托的是 Settings 对象。
在 Gradle 构建时会创建一个 Settings 实例,并根据它执行设置文件。Settings 实例和 settings.gradle 文件是一对一的对应关系。
Settings:声明实例化和配置参与构建 Project 实例的层次结构所需的配置。
项目管理 include
Gradle 支持单项目或多项目构建:
- 单项目构建,
settings.gradle
文件是可选的; - 多项目构建,
settings.gradle
文件是必需的,且必须位于项目的根目录下;
1
2
3
4
5
6
7
// 通过 rootProject.name 强制指定项目名称
rootProject.name = "main"
include(":app", ":libs:someLibrary")
include(":anotherLibrary")
project(":anotherLibrary").projectDir = File(rootDir, "../another-library")
- 项目名称中
:
代表项目的分隔符, 类似路径中的 “/”。 如果以:
开头则表示相对于 root project - 如果子项目不在根项目目录下时则必须使用路径描述, 而不可以使用 “`..:foo” 这种项目相对路径描述:
插件管理 pluginManagement
通过 settings.pluginManagement
相关接口实现的
- repositories: plugin 仓库设置
在 build script 中通过 plugins {…}
引入插件的时候, 默认只从 Gradle 官方插件仓库 查找. 如果我们的插件不在官方仓库, 就需要在这里指定查找的仓库:
1
2
3
4
5
6
// setting script,pluginManagement需要放在第一行
pluginManagement {
repositories { // repositories指定了插件所需要的下载仓库地址。如果自定义的插件发布在私有仓库,就需要在这里加上私有仓库的地址才可以找到你的插件
maven(url = "../maven-repo")
}
}
- resolutionStrategy: Plugin 模块替换
pluginManagement 还支持设置 plugin 的决议策略:
1
2
3
4
5
6
7
8
9
10
// setting script
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.gradle.sample") {
useModule("org.gradle.sample:sample-plugins:1.0.0")
}
}
}
}
看看 PluginResolutionStrategy 源码:
1
2
3
4
5
@HasInternalProtocol
public interface PluginResolutionStrategy {
void eachPlugin(Action<? super PluginResolveDetails> rule);
}
}
PluginResolutionStrategy 允许在 PluginRequest 之前对其进行修改,并有唯一回调 eachPlugin,eachPlugin 的参数类型是 PluginResolveDetails 类型的闭包。
PluginResolveDetails:
1
2
3
4
5
- getRequested:获取请求的插件,返回PluginRequest对象,包含id、version、module信息;
- useModule:设置插件的模块;
- useVersion:设置插件的版本;
- getTarget:请求的目标插件;
- plugin 设置统一版本
插件替换主要用到的就是 useModule
方法:
1
2
3
4
5
6
7
8
9
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.gradle.sample") {
useModule("com.hacket.plugin:gradlexxx:1.0")
}
}
}
}
除了替换 module 以外, 还可以在这里设置版本号,用 useVersion
:
1
2
3
4
5
6
7
8
9
10
// setting script
pluginManagement {
resolutionStrategy {
eachPlugin {
if (requested.id.id == "com.dorongold.task-tree") {
useVersion("1.4")
}
}
}
}
设置过版本后, 在所有的 build script 中通过 plugins {…}
引入插件则无需再次指定版本.
依赖 dependencyResolutionManagement
dependencyResolutionManagement 里面的 repositoriesMode,即 Gradle 对于 allprojects { } 和 subprojects { }中的依赖解析策略。
1
2
3
4
5
6
7
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
repositoriesMode:
- PREFER_PROJECT:默认值,优先使用 build.gradle 中的
repositories { }
,忽略 settings.gradle 中的repositories { }
; - PREFER_SETTINGS:优先 settings.gradle 中的
repositories { }
,忽略 build.gradle 中的repositories { }
; - FAIL_ON_PROJECT_REPOS:表示在 build.gradle 中声明的
repositories { }
会导致编译错误;
如果只有 app 模块,可以把仓库地址都写在 dependencyResolutionManagement>repositories
里面,如果有多个模块,且依赖差别很大,还是建议分开写
如何寻找 settings.gradle?
- 首先会在项目的根目录下找 settings.gradle 文件,如果没找到,则作为单项目构建。
- 如果找到了,会再次校验 include 配置的合法性,不合法,则继续作为单项目构建,合法,则作为多项目构建。
阶段二:Configuration 配置
在 Configuration (配置) 阶段,Gradle 会评估构建项目中包含的所有构建脚本,随后应用插件、使用 DSL 配置构建,并在最后注册 Task,同时惰性注册它们的输入,因为并不一定会执行。
注意:无论请求执行哪个 Task,配置阶段都会执行。所以为了保持构建简洁高效,要避免在配置阶段执行任何耗时操作,类似 android 里面的 onDraw 方法。推荐用 register 替代 create 来创建 Task
Build Script
Build Script 就是模块目录下的 build.gradle(.kts). 每个模块都会有一个 build script 来配置当前模块的构建信息:
- 根目录模块的 build script 叫做 root build script
- 其他子模块的 build script 叫做 module build script.
单模块构建的执行流程大致为: init script -> setting script -> build script
而多模块的构建流程, 比单模块多了一步: init script -> setting script -> root build script -> build script
Gradle 构建时,会根据 Settings 对象解析出来的项目结构为每个项目都创建一个 Project 对象,Project 对象和 build.gradle 文件之间存在一对一的关系。
在 Gradle 生成 Task 依赖关系图之前,Project 对象还做了几件事:
- 引入插件
- 配置属性
- 编译依赖
引入插件
build script 背后是 Project
类型的对象, plugins 是 Project 的一个方法, 用于设置当前模块所使用的插件.
plugins 闭包中还可以通过 version 指定插件的版本, 以及 apply 来决定是否立刻应用插件:
1
2
3
4
5
// plugins是Project对象的一个方法,用于设置当前模块所使用的插件
plugins {
id("com.dorongold.task-tree") version "1.4"
id("com.dorongold.task-tree") version "1.4" apply false
}
配置属性
配置属性,就是对引入的插件进行配置。
- 插件属性
build script 中并没有 android {…} 这个 dsl 属性, 这是 plugin 提供的. 一旦应用了某个插件, 就可以使用插件提供的 dsl 对其进行配置, 从而影响该模块的构建过程。这些插件提供的属性配置 dsl 就相当于插件 init 函数的参数, 最终传入到插件中. 当构建执行的时候就会根据配置对当前模块进行编译.
1
2
3
4
5
6
7
8
9
10
11
plugins {
id("com.android.application")
}
android {
compileSdkVersion(28)
defaultConfig {
// ....
}
}
- 内置属性
Project 对象 本身也提供了很多用于配置构建的 dsl. 我们来看几个常用的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
repositories {
maven {
url = uri(...)
}
}
// 如果 maven 仓库需要认证, 则通过 credentials 添加用户名密码:
repositories {
maven {
url = uri(...)
credentials {
username = "joe"
password = "secret"
}
}
}
- 设置自定义变量: ext
ext 即是 project 对象的一个扩展属性 (ext[“foo”] = …) 又是一个扩展方法 (ext {…}). 它类似于 Map, 可以随意添加 key-value, 相同 key 的 value 会发生覆盖.
在 Kotlin 脚本中, 除了 ext 还有一个 extra 的变量
编译依赖
dependencies { }
里面除了官方库之外,我们还经常在里面添加所需要的三方库,比如 okhttp、glide 等等。
1
2
3
4
5
6
7
8
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
// ...
}
在多项目构建中, 通常 repositories 出现在 root build script 中, 而 module build script 中只包含 dependencies {…} 部分
build script 之间的引用及依赖
默认情况下, 所有的模块是按照字母序进行 evaluate 的. 如果某个模块依赖另一个模块, 则需要使用 evaluationDependsOn
指明依赖关系, 这样被依赖的模块就会优先被 evaluate.
项目属性 vs. 额外属性
项目属性 -P
项目属性 是 Project 上的一个类似 Map 结构的对象属性. 只不过它是只读的, 通过命令行 -P
配置.
我们往往会通过 -P 实现动态的构建参数. 例如, 向构建脚本传入密码等参数:
1
gradle -Ppwd=secret-text ...
这时, 在 build script 中即可通过 property(…) 方法获取到 pwd 的值, 从而防止密码提交到 vcs 而泄漏.
1
2
3
4
5
6
7
8
9
10
repositories {
maven {
url = uri(...)
credentials {
username = "joe"
password = property("pwd")
}
}
}
案例:
1
2
3
// build.gradle中配置
def pwd = property("pwd")
println("pwd=$pwd")
使用 -P 参数:
1
./gradlew -Ppwd=123 clean
额外属性 ext
Gradle 默认为我们配置了一个 key 为 ext
的特殊值, 称为额外属性. 额外属性也是一个类似 Map 的结构:
额外属性最常见的场景是在一个构建过程中定义公共的变量, 例如: 在多模块构建中统一依赖的版本:
1
2
3
4
5
6
7
8
9
10
// root build.gradle.kts定义
ext {
set("kotlin_version", "1.3.50")
}
// xxx/build.gradle.kts使用
dependencies {
// ...
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk7:${property("kotlin_version")}")
}
这样多个版本就可以公用一个变量来统一依赖版本了.
阶段三:Execution 执行
当完成任务依赖图后, Gradle 就做好了一切准备, 然后进入 Execution 阶段. 这个阶段才真正进行编译和打包动作. 对于 Java 而言是调用 javac 编译源码, 然后打包成 jar. 对于 Android 而言则更加复杂些. 这些差异来源于我们应用的插件
在 Execution (执行) 阶段,Gradle 会执行构建所需的 Task 集合。
其实这个阶段才是真正的编译打包,于 Android 而言,比如我们常见的 compileDebugJavaWithJavac、mergeDebugNativeLibs 等等。
Gradle 生命周期监听/Hook
Project 提供的一些生命周期回调方法:
1
2
3
4
afterEvaluate(closure);
afterEvaluate(action);
beforeEvaluate(closure);
beforeEvaluate(action);
Gradle 提供的一些生命周期回调方法:
1
2
3
4
5
6
7
8
9
afterProject(closure),afterProject(action)
beforeProject(closure),beforeProject(action)
buildFinished(closure),buildFinished(action)
projectsEvaluated(closure),projectsEvaluated(action)
projectsLoaded(closure),projectsLoaded(action)
settingsEvaluated(closure),settingsEvaluated(action)
addBuildListener(buildListener)
addListener(listener)
addProjectEvaluationListener(listener)
Initialization Hook (Gradle、Settings 对象可用)
gradle.settingsEvaluated (Setting script 执行结束)
当 settings.gradle(.kts) 被 evaluate 完毕, 此时已经有初始化过的 Settings 对象.
通过 gradle.settingsEvaluated 方法添加 hook, 例如在 setting.gradle(.kts) 中:
1
2
3
4
5
6
// init.gradle.kts or settings.gradle.kts
// 在settings.gradle初始化完毕后调用
gradle.settingsEvaluated { // it为Settings对象
Settings settings = it
println("[settings.gradle] settingsEvaluated init end rootDir=${settings.rootDir}")
}
这个 hook 中可以获取到配置完毕的 Settings 对象。我们通常在这里管理所有构建的插件。
目前我们只能够使用 gradle 和 settings 对象。
gradle.projectsLoaded (创建 Project 对象)
projectsLoaded 是紧接着 settingsEvaluated 的 hook 方法. 我们可以通过 gradle.projectsLoaded 方法添加 hook, 例如在 setting.gradle(.kts) 中:
1
2
3
4
5
// init.gradle.kts or settings.gradle.kts
gradle.projectsLoaded { // it是Gradle对象
Gradle gradle = it
println("[settings.gradle] projectsLoaded. gradleVersion=${gradle.getGradleVersion()}.")
}
projectsLoaded 回调时已经根据 setting script 创建了各个模块的 Project 对象
这时的 project 对象包含了项目的基本信息, 但是尚未被 build script 配置. 因此, 类似于 android {….} 这种在 build.gradle(.kts) 的配置都是取不到的
Configuration Hook (Gradle、Settings 和 Project 可用)
Configuration 阶段, 用于初始化和配置参与到当前构建的所有模块。
Gradle 首先读取 root build script(根目录下 build.gradle(.kts)), 然后是各个子模块。每个子模块的生命周期都一样. 执行的顺序默认是根据模块名的字母序, 可以通过 evaluationDependsOn
设置依赖关系。
Build script 执行前(gradle.beforeProject/allprojects.beforeEvaluate)
在每个 build script 被执行前都会触发对应模块的 beforeEvaluate 和 beforeProject.
- gradle.beforeProject 为所有 project 设置 hook。
- 虽然 beforeProject/beforeEvalute 属于 project 的生命周期, 但是此时 build script 尚未被加载, 所以 beforeEvaluate/beforeProject 的设置依然要在 init script 或 setting script 中进行。
- 不要在 build script 中使用 project.beforeEvaluate 方法. 该 hook 点在执行到 build script 的内容是已经走过了, 所以不会生效
gradle.beforeProject
在各个 module 的 configuration 前执行
1
2
3
4
5
// init.gradle.kts or settings.gradle.kts
gradle.beforeProject {
Project project = it
println("[settings.gradle] === beforeProject ${project.name}")
}
输出:
1
2
3
4
5
> Configure project :
[settings.gradle] === beforeProject GradleDemos
> Configure project :app
[settings.gradle] === beforeProject app
gradle.allprojects beforeEvaluate
在各个 module 的 configuration 前执行,同 gradle.beforeProject
1
2
3
4
5
6
// init.gradle.kts or settings.gradle.kts
gradle.allprojects{
beforeEvaluate {
println("[settings.gradle]=== allprojects beforeEvaluate ${it.name}")
}
}
输出:
1
2
3
4
5
> Configure project :
[settings.gradle]=== allprojects beforeEvaluate GradleDemos
> Configure project :app
[settings.gradle]=== allprojects beforeEvaluate app
Build script 执行后(gradle.afterProject/allprojects.afterEvaluate)
每当一个 build.gradle(.kts) 被执行完毕, 都会产生 afterEvaluate 回调, 代表着 project 被 evaluate 完成. 从此, project 对象内容完整了, 即: 当前 build.gradle(.kts) 中所有的配置项都能够被访问。
一般而言, 我们都会在 build script 中为当前模块配置 afterProject/afterEvaluate;也可以在 settings.gradle 中配置:
1
2
3
4
5
6
7
8
9
10
// init.gradle.kts or settings.gradle.kts
gradle.allprojects{
beforeEvaluate {
println("[settings.gradle]=== allprojects beforeEvaluate ${it.name}")
}
}
gradle.afterProject {
Project project = it
println("[settings.gradle] === afterProject ${project.name}")
}
输出:
1
2
3
4
5
6
7
> Configure project :
[settings.gradle] === afterProject GradleDemos
[settings.gradle]=== allprojects afterEvaluate GradleDemos
> Configure project :app
[settings.gradle] === afterProject app
[settings.gradle]=== allprojects afterEvaluate app
gradle.afterProject/allprojects.afterEvaluate 可以在 settings.gradle 中配置,也可以在 root build.gradle 中配置,后者配置的话那么对于 root build.gradle 本身 beforeEvaluate/beforeProject 加载就打印不出来因为此时已经加载了,afterEvaluate/afterProject 可以正常加载。
projectsEvaluated (所有 Project 配置结束)
projectsEvaluated 是在所有的 build script 都执行完毕后回调
1
2
3
4
5
// init.gradle.kts or settings.gradle.kts
gradle.projectsEvaluated {
Gradle gradle = it
println("[settings.gradle] === projectsEvaluated. gradleVersion=${gradle.getGradleVersion()}.")
}
生成 Task Graph
Gradle 的核心逻辑就是根据 task 的依赖关系生成有向无环图, 然后依次执行图中的 task。 这个 task graph 就是在这个时机生成。
Gradle 没有提供直接的方法设置 hook, 也需要通过 addListener 添加:
1
2
3
4
5
6
7
// init.gradle.kts or settings.gradle.kts
gradle.addListener(object : TaskExecutionGraphListener {
override fun graphPopulated(graph: TaskExecutionGraph) {
....
}
})
Gradle 专门有一个 taskGraph 对象表示任务图. 我们同样可以使用 taskGraph.whenReady 和 addTaskExecutionGraphListener(这两个函数底层是同一套实现, 作用完全一致) 添加 hook:
1
2
3
4
5
// init.gradle.kts or settings.gradle.kts
gradle.taskGraph.whenReady {
....
}
Execution Hook
Task 执行前/后: TaskExecutionListener
Gradle 对每个 task 执行前/后的 hook 点:
1
2
3
4
5
6
7
8
9
// init.gradle.kts or settings.gradle.kts
gradle.addListener(object : TaskExecutionListener {
override fun beforeExecute(task: Task) {
// ....
}
override fun afterExecute(task: Task, state: TaskState) {
// ....
}
})
对于 beforeExecute 而言, 由于还没有真正开始执行 actions, 这时我们还可以对 actions 进行增删改, 从而改变 task 的行为。
Actions 执行前/后: TaskActionListener
Gradle 的 task 是很多 action 的集合, 每个 action 才是执行期间真正运行的代码。
这个 hook 的调用时机位于每个 task 的 beforeExecute 之后或者 afterExecute 之前:
1
2
3
4
5
6
7
8
9
10
// init.gradle.kts or settings.gradle.kts
gradle.addListener(object : TaskActionListener {
override fun beforeActions(task: Task) {
....
}
override fun afterActions(task: Task) {
....
}
})
既然有了 TaskExecutionListener 还会有 TaskActionListener 呢? 这是由于如果某个 task 之前执行并被缓存 (增量编译或者 build cache), 那么 actions 则不会再次被执行. 也就是说, 每次构建过程中, task 的执行一个都不会少, 但是 actions 只会根据需要执行。
构建开始 1 结束: buildFinished
当所有 task 都执行完毕, 整个构建也宣告结束:
1
2
3
4
5
6
7
// init.gradle.kts or settings.gradle.kts
gradle.buildStarted {
}
gradle.buildFinished {
// ....
}
在 gradle 对象中, 大部生命周期都提供了直接的 hook 方法, 例如上面提到的 settingsEvaluated, projectsLoaded 等。 除此之外, gradle 对象还提供了 addListener
和 addBuildListener
两个添加生命周期的方法。
Gradle 生命周期总结
Android Gradle 构建流程:
1
settings.gradle → root build.gradle → app build.gradle → lib build.gradle
settings.gradle
root build.gradle
subprojects
配置所有子 module(Configure project 阶段)
- 源码
1
2
// Project
void subprojects(Action<? super Project> action)
- 示例
1
2
3
4
// root build.gradle
subprojects { subProject ->
println("--------->>>>>>>>>>> [root build.gradle] subprojects ${subProject.name}")
}
输出:
1
2
3
--------->>>>>>>>>>> [root build.gradle] subprojects app
--------->>>>>>>>>>> [root build.gradle] subprojects mylibrary1
--------->>>>>>>>>>> [root build.gradle] subprojects mylibrary2
- 应用
- 为所有的 module 应用相同的配置
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
subprojects { subProject ->
apply from: "$rootDir/build_function.gradle"
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
android {
compileSdkVersion 31
// ...
}
afterEvaluate {
publishing {
publications {
release(MavenPublication) {
from subProject.components.release
groupId = projectConfig.groupId
artifactId = projectConfig.artifactId
version = projectConfig.versionName
}
}
repositories {
maven {
url = localMavenUrl
}
}
}
}
}
allprojects
配置自己及所有子 module(Configure project 阶段)
- 源码
1
2
// Project
void allprojects(Action<? super Project> action)
- 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// root build.gradle
allprojects { project ->
println("--------->>>>>>>>>>> [root build.gradle] allprojects ${project.name}")
}
// 也可以用gradle变量引用
gradle.allprojects { it->
println("[settings.gradle]=== allprojects ${it.name}")
it.beforeEvaluate {
println("[settings.gradle]=== allprojects beforeEvaluate ${it.name}")
}
it.afterEvaluate {
println("[settings.gradle]=== allprojects afterEvaluate ${it.name}")
}
}
输出:
1
2
3
4
--------->>>>>>>>>>> [root build.gradle] allprojects GradleTest
--------->>>>>>>>>>> [root build.gradle] allprojects app
--------->>>>>>>>>>> [root build.gradle] allprojects mylibrary1
--------->>>>>>>>>>> [root build.gradle] allprojects mylibrary2
比 subprojects 多了 GradleTest
Gradle 变量
Gradle 提供的一些生命周期回调方法:
1
2
3
4
5
6
7
8
9
10
11
- StartParameter getStartParameter()
- void allprojects(Action<? super Project> action)
- afterProject(closure),afterProject(action)
- beforeProject(closure),beforeProject(action)
- buildFinished(closure),buildFinished(action)
- projectsEvaluated(closure),projectsEvaluated(action)
- projectsLoaded(closure),projectsLoaded(action)
- settingsEvaluated(closure),settingsEvaluated(action)
- addBuildListener(buildListener)
- addListener(listener)
- addProjectEvaluationListener(listener)
Project 变量
Project 提供的一些生命周期回调方法:
1
2
- beforeEvaluate(closure)/beforeEvaluate(action)
- afterEvaluate(closure)/afterEvaluate(action)
beforeEvaluate/afterEvaluate
module 配置前和配置的监听
1
2
3
4
5
6
7
8
9
10
// settings.gradle
gradle.allprojects { p->
println("[settings.gradle]=== allprojects ${it.name}")
p.beforeEvaluate {
println("[settings.gradle]=== allprojects beforeEvaluate ${it.name}")
}
p.afterEvaluate {
println("[settings.gradle]=== allprojects afterEvaluate ${it.name}")
}
}
StartParameter 启动参数
获取 tasks
1
2
// settings.gradle
println("gradle.startParameter.taskNames=${gradle.startParameter.taskNames}")
输出:
1
2
3
./gradlew clean assembleDebug
gradle.startParameter.taskNames=[clean, assembleDebug]
- 应用
debug 的 task 关掉某些插件
1
2
3
4
5
6
7
8
9
10
11
12
13
buildscript {
ext {
develop = gradle.startParameter.taskNames.any { it.toLowerCase().contains('debug') }
}
repositories {
// ...
}
dependencies {
if (!develop) { // 非debug下才依赖的插件
// DataRanges插件, 对Activity/Fragment/Widgets进行埋点插桩, 开发时可忽略该操作
classpath 'com.bytedance.applog:RangersAppLog-All-plugin:6.5.0'
}
}