让你真正认识这个熟悉的陌生人Gradle

1,769 阅读11分钟

朋友们,是不是经常听人说起Gradle这个大哥,也在项目里面经常看到它的身影,他对于我们来说,没有那么熟悉,他的容貌(语法)好像没有见过,感觉它是不是有点怪怪的。下面将由小德来带领大家了解一下,认识它。

Gradle是什么

1、Gradle 是一个的构建项目的工具,本质上来说是一个项目。 

2、跟AS、Android无关。 

3、Gradle 采用的是一种叫做 Groovy 的语言,更加简单明了。 

4、使用插件的方式创建自定义的构建逻辑。

小朋友问题1:构建系统如何体现的?

经常用的一种方式就是,我们在Modual中的build.gradle中的dependence中定义了OkHttp的依赖,然后点击Sync Now。你会发现项目开始下载依赖了,这就是一种构建过程。(你配置了什么,项目主管就给你申请什么)

小朋友问题2:插件的方式如何体现的?

插件的方式是如下体现的

【1】比如在build.gradle中,有这样的一句话,apply plugin 'android',表示项目中加入了android的插件,它的作用就是提供了和Androd相关的功能 

【2】比如在build.gradle中, classpath 'com.android.tools.build:gradle:0.11.1'这样的一句话,表示引入了gradle的 0.11.1的版本,引入了这样的插件。 

【3】还有在dependence中,引入okHttp的插件。

小朋友问题3:自定义构建逻辑是如何体现的?

自定义构建逻辑体现了一种灵活性

【1】比如你可以在项目中定义构建系统的gradle的版本为1.0还是2.0等等。(现实生活中:你是想用1.0这个人,还是想用2.0这个人) 

【2】比如项目中想解析Json,你是想用Gson呢?还想想用FastJson呢。可以根据你的喜好,自定义构建。

作为Android开发者,我们经常在项目里面听到说Gradle去构建项目,那么究竟AndroidStudio和Gradle的关系是什么?

AS和Gradle的关系

1、Gradle和Android Studio无半毛钱的关系。
2、但是Google 在推出 AS 的时候选中了Gradle 作为构建工具。
3、为了能在AS上使用Gradle,Goole做了一个插件,Android Gradle Plugin**。**
4、在项目的根目录有个build.gradle 文件,里面有这么一句代码:
classpath 'com.android.tools.build:gradle:2.1.2'
这个就是项目引入了Gradle插件的代码,后面的版本表示的是插件的版本,而不是Gradle的版本。这个是Google定的,而和Gradle无关系。

上面对Gradle有一个大致的了解以后,下面我们详细学习Gradle的细节,首先了解一下Gradle的语法。

Gradle语言的语法

Gradle语言的语法,设计下面的两点:

1、脚本转换成对象

gradle是脚本文件,当脚本被执行的时候,他会将脚本转换为一个对象

比如

build.gralde被执行的时候,他会转换成为一个Project对象

settings.gradle被执行的时候,他会转换成为一个Settings对象。

下面的表格展示了不同的脚本对应的不同的对象。

脚本的类型转换的对象
Build 脚本Project
Settings 脚本Settings

2、脚本的结构

一个构建脚本由多个方法块或者方法组成。

比如build.gradle文件中

(1)apply plugin: 'com.android.application' 

它的全称是:project.apply**([plugin: 'com.android.application'])** ,可以看到他是一个方法。  

我们可以看到:project调用了apply方法,方法中传入了一个map参数,其中键为plugin,值为 'com.android.application'

我们再看下面一个例子

(2)

dependencies {
              compile fileTree(dir: 'libs', include: ['*.jar'])
}

dependencies写完整应该是这样的:

project.dependencies(
    {add('compile', 'com.android.tools.build:gradle:2.0.', {})}
)
我们可以看到:project调用了dependencies方法, 方法中传入的是一个闭包,
这个闭包中含有一个add方法,方法中有3个参数。  

结论:

综上,我们可以得出两个结论:
(1)Gradle的难懂就是因为他的简写
(2)Gradle的简洁也是因为他的简写

学习完Gradle的语法以后,我们对Gradle有了一个稍微深入一点的了解,下面我们学习一下Gradle涉及的3个概念,项目,任务,活动

projects , tasks and action

Project

看到下面的图,相信你对项目和任务会有一个全新的概念。

Task

1、表示一个任务
2、你经常会用到两个任务,一个是重新编译项目的任务(task),一个是清理项目的任务(task)。
我们可以看到build和clean任务如下。

3、在主项目的build.gradle文件下有一个任务

task clean(type: Delete) {
    delete rootProject.buildDir
}

表示任务的名称为clean,任务的职责为Delete,删除文件,删除的内容为rootProject的buildDir目录。

如何执行任务

执行任务有两种方式

      一种方式是点击Studio的快捷方式,比如上图中的build和clean,

      一种方式是执行命令的方式。

命令的方式

下面列举了在命令行输入命令的方式来执行任务。

gradlew task -all罗列出所有Task
gradlew assembleDebug导出所有渠道测试包
gradlew assembleRelease导出所有渠道正式包
gradlew assembleBaiduDebug --stacktrace导出指定渠道测试包,同时携带异常信息
gradlew stop立即停止编译
gradlew check检查任务
gradlew build执行了check和assemble
gradlew clean清除所有中间编译结果

例如:在terminate中输入gradlew assembleDebug,可以生成debug包。

学习完项目,任务,活动以后,大家学习一下和这个概念关系非常紧密的一个概念,就是Gradle构建的一个过程

构建生命周期(构建项目的过程-_-)

说的很高大上,就是创建项目的阶段,分为3个阶段

Gradle是一个抽象的概念,他就是一个构建项目的工具,那么它在项目中的反映是什么呢?
在项目中通过文件来配置Gradle的构建过程,一般有下面的7个文件。

Gradle相关文件

local.properties

【1】文件的作用 

 指定了SDK的目录。

 【2】文件的内容 

sdk.dir=D:\ProgramWork\ASSDK

gradle-wrapper.properties(Gradle版本)

1、是什么

gradle-wrapper.properties决定了As中Gradle的版本。

2、gradle-wrapper.properties的内容如下:

#Fri Nov 10 19:53:11 CST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

distributionUrl:是要下载的gradle的地址,使用哪个版本的gradle,在这里修改

3、内容解释

gradle的三种版本:

【1】gradle-xx-all.zip:是完整版,包含了各种二进制文件,源代码文件,和离线的文档。 例如:services.gradle.org/distributio… 

【2】gradle-xx-bin.zip:里面只包含了二进制文件(不包含源码和文档) 例如:services.gradle.org/distributio… 

【3】gradle-xx-src.zip:里面包含了gradle的源码不能用来编译你的工程 例如:services.gradle.org/distributio…

下载位置

zipStoreBase和zipStorePath组合在一起,用来存放下载的gradle-3.3-all.zip所存放的位置
zioStorePath是zipStoreBase目录下的子目录

解压位置

distributionBase和distributionPath组合在一起,是用来存放解压gradle-3.3-all.zip之后文件存放的位置 distributionPath是distributionBase是指定目录下的子目录

注意: 下载位置可以和解压位置不一样

zipStoreBasedistributionBase两种取值:GRADLE_USER_HOMEPROJECT GRADLE_USER_HOME:表示用户的目录。

在window下%USERPROFILE%/.gradle 例如:C:\User<user_name>.gradle\ 

PROJECT:表示当前工程的目录

4、As首次加载Gradle的流程

【1】去https\://services.gradle.org/distributions/gradle-3.3-all.zip 下载gradle-3.3版本,因为是all,所以包含二进制文件,源码,文档 

【2】存放在zipStoreBase目录下的zipStorePath目录,也就是C:\Users<user_name>.gradle\wrapper\dists\gradle-3.3-all<url-hash>\目录下,

全路劲为 C:\Users\Administrator.gradle\wrapper\dists\gradle-3.3-all\55gk2rcmfc6p2dg9u9ohc3hw9  

gradle-3.3-all目录是根据下载的gradle的文件名来命名的,目录是根据distribution url目录字符串计算md5值得来的。

【3】解压gradle-3.3-all.zip,将解压下的文件存放在C:\Users<user_name>.gradle\wrapper\dists中

到现在为止,终于知道了为什么打开一个项目巨慢了吧?因为因为AS回去下载gradle。

5、AS再次打开项目如何加载gradle的流程

第一步:AS打开一个项目的时候,首先会去读取**gradle-wrapper.properties**文件,从而知道这个工程需要**哪个版本**的gradle。
第二步:然后就回去保存gradle的文件夹**GRADLE_USER_HOME**,去看看是不是存在这个版本的gradle,不存在去下载对应的gradle。

settings.gradle(Module管理大臣)

**1、文件的作用 **

 【1】决定哪些Module会被build 。

【2】 会在初始化的阶段执行。

2、如何增加项目的编译速度?

1、当项目中模块比较多时,编译时比较慢的。
2、所以我们可以将项目中的没有涉及的模块注释掉,这样可以极大的提高的编译速度。

Project 中的 build.gradle(通用公告)

1、是什么

所有模块通用的配置信息。

模块下的 build.gradle

1、是什么?

【1】模块下的build.gradle只能用于当前模块,你可以覆盖主目录下的build.gradle文件中的内容。

【2】主要分为3个模块:apply plugin,android,dependencies

gradle.properties(配置公共依赖)

1、是什么?

【1】配置了一些公共的依赖。

【2】可以让多个库公用这个依赖,以便出现库冲突的问题。

2、文件的内容

# Project-wide Gradle settings.

# IDE (e.g. Android Studio) users:
# Gradle settings configured through the IDE *will override*
# any settings specified in this file.

# For more details on how to configure your build environment visit
# http://www.gradle.org/docs/current/userguide/build_environment.html

# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
org.gradle.jvmargs=-Xmx4096m

# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true

COMPILE_SDK_VERSION=26
BUILDTOOLS_VERSION=26.0.2
MIN_SDK_VERSION=19
TARGET_SDK_VERSION=24

android.enableBuildCache=true
org.gradle.daemon=false
android.enableAapt2=false

#公共依赖
DPDCJunit = junit:junit:4.12
DPDCAndroidAppCompatV7 = com.android.support:appcompat-v7:26.0.2
DPDCAndroidDesign = com.android.support:design:26.0.2
DPDCAndroidRecyclerView = com.android.support:recyclerview-v7:26.0.2
DPDCAndroidBaseRecyclerViewAdapterHelper = com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.30
DPDCAndroidButterKnife = com.jakewharton:butterknife:8.8.1

DPDCOkhttp3 = com.squareup.okhttp3:okhttp:3.10.0
DPDCGlide = com.github.bumptech.glide:glide:3.8.0
#??
DPDCGlideOkHttp = com.github.bumptech.glide:okhttp3-integration:1.4.0@aar
DPDCGson = com.google.code.gson:gson:2.8.0
DPDCFASTJSON = com.alibaba:fastjson:1.1.68.android
DPDCEasyPermissions = pub.devrel:easypermissions:0.2.1
DPDCEventBus = org.greenrobot:eventbus:3.1.1

#google
DPDCFindBug = com.google.code.findbugs:jsr305:3.0.0

注意 1、我们可以看到其中有一些公共的依赖,DPDCAndroidButterKnife = com.jakewharton:butterknife:8.8.1 比如ButterKnife,这样在库里面就可以用这些依赖了。

3、在modual的build.gradle中就引用他们

apply plugin: 'com.taobao.android.emas'
apply from: 'common.gradle'

android {
    compileSdkVersion Integer.parseInt(project.COMPILE_SDK_VERSION)
    buildToolsVersion project.BUILDTOOLS_VERSION

代码解析: 

1、project.COMPILE_SDK_VERSION是一个String类型的值 

2、compileSdkVersion 需要的是一个int类型的值,所以我们需要将这个值转换成int值。

config.gradle(全局配置)

1、是什么?

项目中经常会使用相同的配置,例如不同module中都要配置compileSdkVersionbuildToolsVersion 等变量值,我们把这些公共的配置项称为共享变量

一般情况下,它们的取值都应该保持一致,如果让每个module自己管理这些配置的值,则可能会导致不同module取值不同,为了解决这个问题,我们定义一个名为common_config.gradle 的文件,并放在工程根目录中。 

2、如何配置?

第一步:在项目根目录下创建一个config.gradle文件

ext {
    cfgs = [
            compileSdkVersion    : 26,
            buildToolsVersion    : "26.0.2",
            minSdkVersion        : 14,
            targetSdkVersion     : 26,
            versionCode          : 10,
            versionName          : "2.0.0",
            ucropVersionCode     : 22,
            ucropVersionName     : "2.2.0-native",

            //open version control
            androidSupportVersion: "26.0.2",
            glide                : "3.8.0",
            rxjava               : "2.0.5",
            rxandroid            : "2.0.1"
    ]
}

第二步:在项目的build.gradle文件中引入config.gradle文件

apply from: "config.gradle"

第三步:在Module的build.gradle中通过rootProject.ext.XXXXX来使用

上面学习了Gradle的相关知识,下面我们学习Gradle更高的知识,Gradle打包发布函数库到JCenter和

补充......

Gradle安装

Gradle Wrapper(包装纸)(相当于Gradle的版本的管理者

    (1)Gradle工程可以灵活的配置Gradle版本。

    (2)无需手动下载安装,配置版本即可自动下载。

AS中的Gradle Wrapper如下

根据上面的路径,Gradle Wrapper会自动的帮我们下载

Gradle细节介绍

gradlew和gradler.bat

gradlew:linux上的使用,是Gradlew的启动脚本

gradlew.bat :windows上的使用,是Gradlew的启动脚本

通俗点讲:就是通过它来启动Gradle。

gradle和settings关系

gradle会根据settings.gradle的配置来导入指定目录下的工程。

build.gradle

告诉项目,应该怎么配置,比如下载那些依赖,使用那些远程仓库,需要配置哪些插件等。

gradle.properties

gradle 属性配置文件,值会添加到gradleproject对象当中去。

比如在gradle.properties中配置了COMPILE_SDK_VERSION=29 

然后在项目的build.gradle中通过project.COMPILE_SDK_VERSION来使用

Gradle作用

1、去哪找构建插件,去哪个仓库maven,jcenter找插件。

比如在项目的build.gradle中,buildscript中有如下,说明插件从google或者从jcenter中找

repositories {    
    google()    
    jcenter()
}

2、找哪些构建的插件,比如kotlin的插件。

比如在项目的build.gradle中,buildscript中有如下,说明要加载gradle和kotlin的插件

dependencies {   
    classpath "com.android.tools.build:gradle:4.0.1"    
    classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"    
    // NOTE: Do not place your application dependencies here; they belong   
     // in the individual module build.gradle files
}

3、去哪找工程依赖,比如maven仓库,jcenter仓库等。

比如在项目的build.gradle-allprojects中全局配置,说明工程的依赖去google()和jcenter()中找。

allprojects {
    repositories {
        google()
        jcenter()
    }
}

4、找哪些工程依赖,比如配置的一些依赖的包,okhttp等。

5、如何构建项目,比如下面的命令,就是gralde在每次构建项目的时候,都会删除build目录,然后重新创建。

task clean(type: Delete) {    
     delete rootProject.buildDir
}

Gradle自定义任务

比如在项目的build.grale中最底部写上如下代码,其中println('Hello') 为准备任务,doLast为任务的执行体。

task hellWorld(group: 'hello'){
    println('Hello')
    doLast {
        println('World')
    }
}

然后点击左侧的三角箭头来执行任务,结果如下

同时在右侧的Gradle中出现hello这个组、helloWorld这个任务。