文章目录
Gradle思想
在软件开发过程中,编码,编译,打包,测试,这几个过程必不可少,这些过程中有些步骤的重复性非常高,在没有构建工具之前,开发人员需要自己手动的编译,手动的打包,这些操作都是可以通过重复的有序的步骤来完成的,Gradle就可以帮助我们自动的编译,打包,从而提高开发的效率和质量;
闭包
Gradle是基于Groovy语言工作的,Groovy语言和java的相似度非常高,这里介绍一个java没有的概念,闭包是一个类:用于描述一个可以接受参数和返回值的代码块;
Closure closure = {
it -> println("闭包")
}
it 是隐式参数,用于描述当前闭包,和java的this差不多
task
task是gradle中一个很重要的概念,代表一个原子性操作,安卓项目的编译,打包的细节,都是通过一个个task来完成的:
task hello() {
print("say hello")
}
task clean(type: Delete) {
delete rootProject.buildDir
doFirst {
println("clean start")
}
doLast {
println("clean end")
}
}
注意doFirst和doLast函数,在下面会详细介绍
gradle 工作流程
在了解Gradle的构建流程前,需要知道两个概念,Project,Task,每一个待编译的工程都叫做Project,每一个Project都包含了多个Task,比如Android APK的编译,可能包括Java源代码编译,资源编译,打包,签名;这些编译任务都是通过一个一个的Task完成的;
Initialization:
初始化阶段,Gradle 将会确定哪些项目将参与构建,并为每个项目创建一个 Project 对象实例。对于 Android 项目来说即为执行 setting.gradle 文件;
一般setting.gradle都是这样的:通过include函数将所有的Project包含进来
include ':app', ':a', ':b'
Configuration:
配置阶段,会解读每一个build.gradle文件,分析里面的task,然后将这些task形成一个有向图,表示task的依赖关系
task testBoth {
println '我会在 Configuration 和 Execution 阶段都会执行'
doFirst {
println '我仅会在 testBoth 的 Execution 阶段执行'
}
doLast {
println '我仅会在 testBoth 的 Execution 阶段执行'
}
}
写在Task闭包的任务会在Configuration阶段运行,而doFirst,doLast会在Execution阶段运行;
切记大部分的内容是写在 doLast{} 或 doFirst{} 闭包中,因为写在如果写在 task 闭包中的话,会在 Configuration 阶段也被执行。
Execution:
task 的执行阶段。首先执行 doFirst {} 闭包中的内容,最后执行 doLast {} 闭包中的内容。
我们可以hook默认的构建过程,加入一些自定义的操作;
Gradle Wrapper
Gradle Wrapper是一个脚本,可以帮助我们自动安装和运行Gradle,只需要指定Gradle的版本就好了
在Android Studio项目中的这些目录,都是和Gradle Wrapper相关的文件:
- gradle-wrapper.jar:gradle运行的逻辑代码
- gradle-wrapper.properties:用来配置gradle的属性文件,主要可以配置以下内容:
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.1.1-all.zip
- distribution相关的两个是配置gradle解压后存放的位置
- zip相关的是存放gradle压缩包存放的位置
distributionUrl
用来Gradle官网以及发版压缩包的下载地址
- gradlew:Linux平台执行gradle命令的脚本文件
- gradlew.bat:Windows平台执行gradle命令的脚本文件
Android插件
构建文件的目录:
- 项目build.gradle:配置项目的整体属性,gradle插件版本,代码仓库
- 模块build.gradle:当前模块的编译设置,下面会具体介绍两个块,Android块和dependency块
- setting.gradle:当前项目引入的模块都需要在这里声明
Android 块
// androdi块
android {
compileSdkVersion 30 // 编译该模块的SDK版本
buildToolsVersion "30.0.2" // Android构建工具版本
// 默认配置块
defaultConfig {
applicationId "com.example.myapplication" // APP包名
minSdkVersion 23 // 支持的最低SDK版本
targetSdkVersion 30 // 基于开发的SDK版本
versionCode 1 // App内部的版本号
versionName "1.0" // App版本名称,发布的版本号
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" // 单元测试使用的Runner
}
// 用于配置构建不同的apk,debug,release
buildTypes {
// release apk
release {
minifyEnabled false // 是否混淆
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' // ProGuard混淆使用的混淆配置文件
}
// debug apk
debug{
applicationIdSuffix ".debug" // 添加 applicationId 的后缀
debuggable true // 是否支持断点调试
}
}
signingConfigs{
storeFile file("C:/...") // 签名证书文件
stroePassword "" // 签名的密码
storeType "" // 签名证书的类型
keyAlias "" // 签名证书密钥的别名
keyPassword "" // 签名证书中密钥的密码
}
}
dependency块
用于配置该module构建过程中所有依赖的库,可以使用两个函数来依赖:
- implementation:可以让模块在编译时隐藏自己使用的依赖,但是在运行时对所有模块是可见的
- api:无法在编译时隐藏使用的依赖,如果一个模块发生变化,整条依赖链上的模块都需要重新编译,而使用implementation只会重新编译这个模块
全局配置
如果有多个模块,可以使用一个全局配置将所有模块进行统一管理
- 在项目build.gradle 中使用ext块:
ext{
compileSdkVersion = 28
minSdkVersion = 15
targetSdkVersion = 27
}
// 在模块build.gradle中使用
targetSdkVersion rootProject.ext.targetSdkVersion
Gradle 依赖管理
- transitive:禁止依赖传递
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'{
transitive false
}
- force:强制这个库使用统一版本
在模块build.gradle中添加如下代码
configurations.all {
resolutionStrategy{
force 'androidx.appcompat:appcompat:1.1.0'
}
}
- exclude:排除库依赖传递中设计的库
compile ('com.xxx.wireless.xx-update:1.0.17'){
exclude(group: 'com.xxx.wireless.xx', module: 'xx-tools')
}
组件化搭建:
1.版本统一管理
- 新建一个gradle文件,生命一些变量,用于全局配置
ext {
isRelease = false
configMap = [
compileSdkVersion : 28,
applicationId : "com.leap.latte",
minSdkVersion: 23,
targetSdkVersion:28,
versionCode : 1,
versionName : "1.0"
]
}
- 在根build.gradle文件中 引入 apply from: ‘config.gradle’ 才能使用
apply from: 'config.gradle'
- 使用配置统一管理,在各个build.gradle中都可以使用
compileSdkVersion configMap.compileSdkVersion
2. 组件的Release和Debug自动切换
if (isRelease){
apply plugin: 'com.android.library' // 不可以独立运行 不需要applicationId,依赖app壳
}else {
apply plugin: 'com.android.application' // 可以独立运行 需要 applicationId ,不依赖app壳
}
3. Gradle变量在Java中使用
android {
compileSdkVersion configMap.compileSdkVersion
defaultConfig {
applicationId "com.leap.latte"
minSdkVersion 23
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// gradle 的变量放到java用
buildConfigField("boolean","isRelease",String.valueOf(rootProject.isRelease))
}
}
sync后会生成Java类BuildConfig
/**
* Automatically generated file. DO NOT MODIFY
*/
package com.leap.latte;
public final class BuildConfig {
public static final boolean DEBUG = Boolean.parseBoolean("true");
public static final String APPLICATION_ID = "com.leap.latte";
public static final String BUILD_TYPE = "debug";
public static final String FLAVOR = "";
public static final int VERSION_CODE = 1;
public static final String VERSION_NAME = "1.0";
// Fields from default config.
public static final boolean isRelease = false;
}