Gradle 权威指南-note1

1.Gradle入门

Gradle是一个非常优秀的构建系统工具,它的DSL基于Groovy实现。

1.1 配置Gradle环境

grdle需要Java环境,要求JDK 6 以上,并且要配置Java的环境变量。

Gradle文件说明
官网下 https://gradle.org/ 载,得到压缩包 gradle-2.14.1-all.zip 。然后解压。得到目录清单

1.docs API DSL 指南文档
2.getting-started.html
3.init.d gradle初始化脚本目录
4.lib
5.LICENSE
6.media icon 资源
7.NOTICE
8.sample 示例
9.src 源文件

然后把GRADLE_HOME/bin添加环境变量路径里。
执行:
gradle -v 可以查看是否安装成功。
如果要在AS里执行,记得重启AS.

task hello{
	doLast{
		println "hello world"
	}
}

执行命令:gradle -q hello
-q 参数用于控制gradle输出的日志级别

1.2.Gradle Wrapper

是对gradle的包装,便于团队开发过程中统一Gradle构建的版本。这样大家可以使用统一的Gradle版本进行构建。wrapper在window下一个处理脚本,在linux下是一个shell脚本。他会检查Gradle有没有被下载关联。

  1. 生产wrapper
    gradle提供了内置的Wrapper Task帮助我们自动生成Wrapper所需的文件目录。在一个项目的根目录输入gradle wrapper即可生成。

gralde wrapper
distributionBase=GRADLE_USER_HOME 主目录
distributionPath=wrapper/dists 相对distributionBase的路径
zipStoreBase=GRADLE_USER_HOME 同distributionBase
zipStorePath=wrapper/dists
distributionUrl=https://services.gradle.org/distributions/gradle-6.5-bin.zip Gradle发行版压缩包的下载地址。

1.3.自定义Wrapper

gradle-wrapper.properties由wrapper task生产的。我们可以自定义wrapper task任务来达到配置gradle-wrapper.properties。

task wrapper(task:Wrapper){
	gradleVersion = '2.4'
}

distributionBase=GRADLE_USER_HOME
//下载gradle的路径
distributionUrl=https://services.gradle.org/distributions/gradle-6.7.1-bin.zip
distributionPath=wrapper/dists
zipStorePath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

1.4 gradle 日志

ERROR
QUIET
WARNING
LIFECYCLE 进度消息
INFO
DEBUG

输入Quiet级别之上的日志
gradle -q tasks

a 错误堆栈信息

默认情况下,堆栈信息是关闭的。需要我们通过命令行的堆栈信息开关打开它。
-s or --stacktrace 输出关键性信息
-S or --full-stacktrace 输出详细信息

b logger. 日志调试

logger.quiet("")
logger.error("")

1.5 gradle 命令行

./gradlew 是Mac的命令,如果你是window,输入gradle
使用帮助

./gradlew -?
./gradlew -h
./gradlew -help

强制刷新依赖

./gradlew --refresh-dependencies assemble

多任务调用
有时候我们要同时运行多个任务,比如执行jar之前,先clean

./gradlew clean jar

通过任务名字缩写执行
比如有个任务connectCheck
可以执行:

./gradlew cc

2.Groovy基础

Groovy是基于JVM的一种动态语言,Groovy完全兼容Java,有在此增加很多动态类型和灵活的特性。如 闭包 DSL

2.1 字符串

Groovy不需要分号,单引号和双引号都可以。

def str1 = "hello"
def str2 = 'hello'

单引号没有运算能力,表示常量字符串。双引号可以直接运行表达式计算。

task testStr{
    def name = "lisi"
    println '单引号的变量计算:${name}'
    println "双引号的变量计算:${name}"
}

单引号的变量计算:${name}
双引号的变量计算:lisi

2.2 集合

Groovy完全兼容Java的集合,且进行了扩展。
list set map Queue

list

def numlist = [1,2,3,4] 使用索引访问集合
println numlist.getClass().name

println numlist[1] 获取第二个元素
println numlist[-1] 访问最后一个元素
println numlist[1..3] 访问第二个到第四个元素

numlist.each{
	println it
}

map

def map = ['width':1024,'height':768]
println map['width'] 获取width
println map.height 获取值

map.each{
	println "key:${it.key},Value:${it.value}"
}

groovy还提供了collect、find、findAll

2.3 方法

def method(int a,int b){
	println a+b
}
task invokeMethod<<{
	method(1,2)
	method 1,2 //括号可以省略
}

return 可以不写,最后一句作为返回值。

代码块是可以作为参数传递的

numlist.each({println it})

2.4 JavaBean

class Person{
	private String name
}

task hellJava <<{
	person p = new Person()
	p.name ="lisi"
	println "名字是:${p.name}"
}

2.5 闭包

闭包就是一段代码块

task helloClosure<<{
    customEach{
        print it
    }
}
//closure参数用于接收闭包(代码块)
def customEach(closure){
    for (i in 0..<10) {
        closure(i)
    }
}

传递参数

我们为闭包传递了两个参数,key .value


task helloClosure  {
    eachmap { K, V ->

        println "$K  $V"
    }
}

  def eachmap(closure) {
    def map = ["one": 1, "two": 2]
    map.each {
        closure(it.key, it.value)
    }
}

闭包委托

闭包的强大之处在于支持闭包方法的委托。Groovy的闭包有thisObject、owner、delegate三个属性。
当你在闭包内调用方法时,有它们来确定使用哪个对象来处理。默认delegate/owner是相等的。但是delegate可以被修改的。Gradle中的闭包的很多功能都是通过修改delegate实现的。

task helloDelegate  {

    new Delegate().test {
        println "thisObject:${thisObject.getClass()}"
        println "owner:${owner.getClass()}"
        println "delegate:${delegate.getClass()}"

        method1()
        it.method1()
    }
}
def method1() {
    println "context this:${this.getClass()} in root"
    println "method1 in root"
}
class Delegate {
    def method1() {
        println "Delete this:${this.getClass()} in Delegate"
        println "method1 in Delegate"
    }

    def test(Closure<Delegate> closure) {
        closure(this)
    }
}

result:

thisObject:class build_9eq7gfn6et0rl6qz17rvoqogw
owner:class build_9eq7gfn6et0rl6qz17rvoqogw$_run_closure2
delegate:class build_9eq7gfn6et0rl6qz17rvoqogw$_run_closure2
context this:class build_9eq7gfn6et0rl6qz17rvoqogw in root
method1 in root
Delete this:class Delegate in Delegate
method1 in Delegate

thisObject的优先级最高。默认情况下,优先使用thisObject来处理闭包中调用的方法,如果有则执行。thisObject其实就是这个构建脚本的上下文,它和脚本中的this对象是相等的。

列子中也证明delegate和owner是相等的,两个的优先级是:owner比delefate高。所以闭包内方法的处理顺序是:thisObject>owner>delegate。

2.6 DSL 领域特定语言

DSL (domain specific Language)领域特定语言。专注某个领域的语言。Gradle就是一个DSL.基于Groovy,专门解决自动化构建的DSL.

3.Gradle构建基础

3.1 setting文件

用于初始化及工程树配置。为了配置子工程。
子工程只有在settting文件里配置了才能识别、

3.2 build.gradle文件

每个project都会有一个build.gradle文件,它是project构建入口,配置版本,依赖库,配置插件。
Root Project也可以获取所有child project,比如Java在开发大型项目的时候,会有很多模块,每个模块都是project。

subprojects {
	apply plugin "java"
    repositories {
       		jecenter()
       }
    }
}

3.3 projects 及Tasks

gradle中,可以有很多project,可以定义project生成jar,生成war包,也可以创建project用于上传war文件。一个project又包含多个task。
task是一个操作,一个原子性操作。比如打个jar包,复制一分文件,编译一次Java代码

task xxxx{
    doOne{
        println 'hello'
    }
     
}

3.4 创建一个任务

task customTask1{
    doFirst{
        println "this is task"
    }
    doLast{
    	println "this is last"
    }
}

task是一个关键字,它是project对象的一个函数,原型为create(String name,Closure configureClosure),customTask1是任务的名字;第二个参数是闭包,大括号里的代码。

tasks.create("customTask2"){
    doFirst {
        println "one"
    }
    doLast {
        println "two"
    }
}

3.5 任务依赖

dependsOn是Task类的一个方法,可以接收多个依赖的任务作为参数。

task hello  {
    println "hello"
}
task exMain (dependsOn:hello){
    doLast {
        println "main"
    }
}

还可以依赖多个task

task exMain (){
    dependsOn hello,world
    doLast {
        println "main"
    }
}

3.7 自定义属性

project和Task 都可以让用户添加额外的自定义属性,使用ext

ext.name = 'lisi'
ext{
    phone =890
    address = 'hello'
}
task one{ 
    println "$name"
    println "$phone"
    
}

自定义属性还可以使用在sourceSet中,


sourceSets.all{
    ext.resourceDir = null
}

sourceSets{
    
    main{
        resourcesDir ='/main'        
    }
    
    test{
        resourcesDir ="/test"
    }
}

4.Gradle 任务

1.多种方式创建任务

依赖于project给我们提供的快捷方法及TaskContainner提供的相关Create方法,可以有多种方式来创建任务。


def Task createTask = task(createTask)

createTask.doLast {

    println "hello world"
}

createTask就是任务名字,可以使用.gradlew createTask 来执行这个任务。这种方式的创建其实调用project对象中的task(String name)的方法
第二种方式 以一个任务名字+ 一个对该任务配置的map对象来创建任务。

def Task createTask2 = task(createTask2,group: BasePlugin.BUILD_GROUP)

第三种:任务+闭包

task createTask3{
    decription "演示"
    doLast {
        println "this is task + closure style"
    }
}

2.多种方式访问任务

我们创建的任务都会作为项目(project)的一个属性,属性名就是任务名,可以直接通过该任务名字访问和操作该任务;

其次,任务都是通过TaskContainer创建的,它是我们创建任务的集合,在project中我们通过tasks属性访问TaskContainer.访问的时候,任务名就是key

再则,通过路径访问,一个是get 一个是find,区别为get的时候如果找不到会抛出异常UnknowTaskException。而find找不到返回null。

通过名称访问,也有get 和find 两种,区别和上述一样。

3.任务分组和描述

任务分组就是分类,便于对任务进行归类整理。任务的描述就是说明这个任务有什么作用。

4.<< 操作符

<< 操作符在gradle的task是doLast的短标记形式。

5.任务的执行分析

当我们执行一个Task的时候,其实就是执行其拥有的actions列表,这个列表保存在Task对象实例中的actions成员变量中,其类型是一个List

List<ContextAwareTaskAction> actions = new ArrayList<>()

我们把task之前执行、task本身执行、task之后执行分别称为doFirst 、doSelf、doLast

Task task = task two(type: CustomTask)

task.doFirst {
    println '之前执行'
}
task.doLast {
    println '之后执行'
}

class CustomTask extends DefaultTask {
    @TaskAction
    def doSelf() {
        println 'task 自身执行'
    }
}

6.任务排序

通过shouldRunAfter和mustRunAfter这两个方法,可以控制一个任务应该或者一定在某个任务之后执行,你可以控制任务的执行顺序,而不是通过强依赖的方式。

taskB.shouldRunAfter(taskA) 表示taskB 应该在taskA执行之后执行,这里的应该不是必须,有可能任务顺序不能按照预期完成。而mustRunAfter(taskA) 表示严格执行。

7.任务的启用和禁用

Task中有个enable属性,用于启用和禁用任务。默认true,表示启用。

8.任务的OnlyIf断言

断言就是一个条件表达式,Task有一个onlyif方法,接受一个闭包作为参数。如果该闭包返回ture表示任务执行。否则跳过。

9.任务规则

我们创建的任务都有TaskContainer进行管理,所以当我们访问任务的时候都是通过TaskContainner进行访问,而TaskContainner继承NamedDomainObjectCollection,所以任务规则其实就是NamedDomainObjectCollection的规则

5.Gradle 插件

1.作用

1.添加任务到项目,测试,编译,打包

2.添加依赖配置

3.向现有的对象类型添加新的扩展属性,帮助我们优化构建,eg:android{} 就是

4.对项目进行约定修改,应用Java插件后,约定src/main/java目录下是源码存放位置,

2.如何应用插件

2.1应用二进制插件

二进制插件就是实现了org.gradle.api.Plugin接口的插件,有PluginId

apply plugin:'java'

'java’是Java插件的plugin Id,他是唯一的。

apply plugin:org.gradle.api.plugins.JavaPlugin

因为包是默认导入的,可以去除
apply plugin:JavaPlugin

二进制插件一般被打包到jar里独立发布

2.2 应用脚本插件

应用脚本插件就是把这个脚本加载进来,使用from,后跟一个脚本文件,额可以本地,可以网络。

可以把脚本文件,进行分块,分段整理,拆分成共用、职责分明的文件。然后使用apply from来引用

apply from:'version.gradle'

apply 其他用法

void apply(Map options);
void apply(Closure closure);
void apply(Action action);
2.3 第三方发布的插件

第三方发布的作为jar的二进制插件,先在buildscript{}配置其classpath才能使用。

buidlscript{}块是构建项目之前,为项目进行前期准备和初始化相关配置依赖的地方。

buildscript {
    repositories {
 		google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.3'
    
    }
}

3.自定义插件??

6.java Gradle 插件

1.如何应用插件

apply plugin:'java'

Java插件会为你的工程添加有用的默认设置和约定,如源代码位置,单元测试代码位置,资源文件位置。遵循默认就好。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-p80UUp57-1637833595185)(C:\Users\chents\Pictures\6-1.png)]

src/main/java 源代码

src/main/resources 资源

src/test/java 单元测试源代码

src/test/resources 单元测试资源

main和test 是Java插件内置的两个源代码集合,也可以自定义添加

sourceSets{
    vip{
        
    }
}
//这样就会新建vip/java  vip/resources目录

默认情况不需要这种目录结构;如果你想改变:

sourceSets {
    main {
        java{
            srcDir 'src/java'
        }
        resources {
            srcDir 'src/resources'
        }
    }
}

2.配置第三方依赖

1.要使用第三方依赖,第一个告诉gradle去哪找到这些依赖,使用什么类型的仓库

buildscript {
    repositories {
 
        google()
        mavenCentral()
    }
}

有了仓库,告诉gradle依赖什么

group

name

version

  dependencies {
  		compile group:'com.android.tools.build',name:'gradle',version:'4.2.2'
  		//也可以写成下面形式
        compile "com.android.tools.build:gradle:4.2.2"
      
    }

compile:编译时依赖

testCompile 编译单元测试依赖,不会打包到apk里

name 继承 任务 msg
compile compileJava 编译时依赖
runtime compile 运行时依赖
archives uploadArchives 项目发布构建

3.构建Java项目

gradle中,执行任何操作都是任务驱动。

build任务:编译源码,处理资源,打包jar 编译测试用例,处理测试资源,运行

clean 删除生产的文件

assemble 不执行单元测试,只会编译打包

check 执行单元测试

javadoc生产api文档

4.sourceSets概念

sourceSets源集,是Java插件描述管理代码及资源,一个Java源代码和资源文件的集合。sourceSets是一个SourceSetContainer,可以查阅api.

name
output.classesDir  编译后目录
output.resourcesDir 编译后资源目录
java Java源文件
java.srcDirs Java源文件所在目录
resources 资源文件
resources.srcDirs 资源文件所在目录

sourceCompatibility 编译Java源文件使用的Java版本
targetCompatibility 编译生成的类的Java版本

5.多项目构建setting.gradle

rootProject.name = "Gradle_demo"
include ':app1'
include ':app2'
    
project(':app1').projectDir = new File(rootDir,'/app1')
    

subproject

可以在project的gradle文件里让所有子项目应用插件

subproject{
    apply plugin 'com.android.application'
}

6.发布构件

如果你的项目是一个库工程,要发布jar给其他人使用,gradle提供了方便的配置发布的功能。发布到本地目录、maven库、Ivy库。

task pushlish(type:Jar)

artifacts {
    archives pushlish
}

//发布你的打包文件 到本地
uploadArchives {

    repositories {

        flatDir {
            name 'libs'
            dirs "$projectDir/libs"
        }
    }
}

//发布你的打包文件 到maven仓库
uploadArchives {
    repositories {
        mavenDeployer {
            repository(url: Mavens.SNAPSHOTS_URL) {
                authentication(
                        userName: Mavens.SNAPSHOTS_USERNAME,
                        password: Mavens.SNAPSHOTS_PASSWORD
                )
            }
            pom.project {
                version '1.0-SNAPSHOT'
                artifactId 'widgets'
                groupId 'com.xxx.xx'
                description 'upload AAR'
            }
        }
    }
}

uploadArchives是一个upload Task,用于上传我们的构件。

7.android Gradle 插件

1.插件分类

app插件id: com.android.application

library插件id: com.android.library

test插件id: com.android.test

1.配置应用Android Gradle 插件

dependencies {
    classpath "com.android.tools.build:gradle:4.2.2"
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.5.20"

}

2.就可以在module使用了

apply plugin:' com.android.application'
android {
    compileSdk 31
}

android{}是Android 插件提供的一个扩展类型。

2.Android 工程

android{}是Android 插件提供的一个扩展类型。对Android Gradle工程进行自定义的配置,实现是com.anroid.build.gradle.AppExtension.是project的一个扩展。可参阅API

compileSdkVerison 编译Android SDK的版本
buildToolsVersion Android构建工具的版本,eg:appt、dex工具
defaultConfig 默认配置,是一个ProductFlavor,他允许我们根据不同情况产生多个不同的apk。渠道打包
buildTypes 是一个NamedDomainObjectContainer类型,是域对象。类似sourceSet。包含release/debug等。我们还可以新增构建的类型。release就是一种buildTypes

minifyEnabled 是否混淆
proguardFiles 混淆的管理文件,哪些文件进行混淆

3.Android Gradle任务

assemble

check

build

connectedCheck

deviceCheck

lint

install uninstall

clean

8.自定义Android Gradle 工程

1.defaultConfig默认配置

defaultConfig是一个ProductFlavor,

//
defaultConfig {
    applicationId "com.example.gradle_demo"
    minSdk 21
    targetSdk 31
    versionCode 1
    versionName "1.0"

    testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

applicationId是ProductFlavor的一个属性,用于指定生成APP的包名,默认情况下为null。默认会从AndroidManifest.xml读取。

minSdkVersion是ProductFlavor的一个方法。指定最低支持的Android版本。

targetSdkVersion

testApplicationId 用于配置测试APP的包名

testinstrumentationRunner 用于配置单元测试用的Runner.默认使用android.test.InstrumentationTestRunner

signingConfig 配置默认签名信息,对生成的APP签名

2.配置签名信息

一个APP只有在签名后,才能被发布、安装、使用。一般有debug和release两种模式。

signingConfigs {
    debug {
        keyAlias keystoreProperties['keyAlias']
        keyPassword keystoreProperties['keyPassword']
        storeFile file(keystoreProperties['storeFile'])
        storePassword keystoreProperties['storePassword']
    }
    release {
        keyAlias keystoreProperties['keyAlias']
        keyPassword keystoreProperties['keyPassword']
        storeFile file(keystoreProperties['storeFile'])
        storePassword keystoreProperties['storePassword']
    }
}

3.构建的应用类型

applicationIdSuffix

applicationIdSuffix是buildTypes的一个属性,配置基于applicaitonId的后缀。如applicationId为com.example.xx,我们指定applicationIdSuffix为.debug. 那么生成的debug apk的包名为com.example.xx.debug

debuggable

debuggable是buildTypes的一个属性,用于配置是否生成一个可供调试的apk。true或者false

jniDebuggable和debugable类似,配置是否可供调试Jni(C/C++)的apk

multiDexEnabled 用于配置buildTypes是否启动自动拆分多个dex的功能,当app方法总量超过65535个方法的时候使用。

shrinkResources 用于配置是否自动清理未使用的资源。默认为false

4.启动混淆

5.启动zipalign优化

zipalign是Android为我们提供整理优化apk文件的工具,提高系统和应用的运行效率,更快地读写apk中的资源,降低内存使用。

defaultConfig {

	zipalign true
}

你可能感兴趣的:(读书笔记,java,Gradle,android,Groovy)