Gradle

Gradle详解

每次学习一个新的知识,发现最难的地方在于对这个知识的整体构建,各种概念的认识和理解。像上次学习单元测试,一大堆的框架绕来绕去,不同的博客讲解的又比较分散,不系统。学习Gradle的初衷在于想了解Android项目的构建流程,并且可以自己去控制构建流程。

先提供参考博客和网址。

1.http://www.infoq.com/cn/articles/android-in-depth-gradle/ [这一篇对Gradle的分析和讲解很详细,对理解Gradle有很大的帮助]
2.https://docs.gradle.org/current/dsl/org.gradle.api.Task.html [Gradle官网,可以看一些常见的DSL]
3.http://google.github.io/android-gradle-dsl/current/index.html [Android DSL文档]
4.http://jiajixin.cn/2015/08/07/gradle-android/ [这一个是从配置脚本的角度来讲解的,如果只是想在学一下怎么配置看这篇就可以了]
5.https://dongchuan.gitbooks.io/gradle-user-guide-/content/dependency_management_basics/dependency_configurations.html [Gradle User Guide 中文版]
书籍方面,目前市面上就两本:
1.Gradle in action [这本书我买了,话说第一次买专业书籍不是Android,不是java,是它。讲解的太细,好多次看的我想睡觉,重点是里面的示例没有Android方面的,可以作为对Gradle的整体认识之用]
2.Gradle User Guide [这本书没买,看的网上中文版,给力,尤其是Task那一章,网址见上方]


下面开始Gradle学习之路。

大家都知道Gradle是一个构建工具,那么它是怎样实现各种不同工程的构建的呢?比如,java工程的自动打包,运行等。Android工程的自动打包,安装,lint检查,卸载等。其实具体怎么做的,跟Gradle无关,Gradle可以理解成一个框架(跟Eclipse一样,可以根据不同的插件开发不同的工程),Gradle用java插件就可以构建java工程,用了android插件就可以构建android工程。
那么插件是怎么引入的呢?不急,我们先了解一下Gradle的两个概念,Project和Task。
对于Gradle来说,每一个app,library或者Module都是Project;对于Project,Gradle要求在其根目录下必须有一个build.gradle,相当于Maven的pom.xml文件。有了这个文件,Gradle就可以构建工程了。看到这,你可能要问了,你看Android工程,除了Module层有一个build.gradle文件,在Top Project层明明还有一个build.gradle和setting.gradle的嘛,这你怎么解释?
解释在这:想象一下这种场景,我们的Project有多个Module,那不是每次都要cd到每一个Module中去执行build.gradle?所以这里引入了Multi-Projects Build,即多项目构建。要实现多项目构建,只需一步:
在Top Project根目录添加setting.gradle文件,这里就一句:include ‘:app’ ,这句代码就是引入Module,如果有10个Module,这里就是10个。
你又要问了,那还有一个build.gradle呢?说句实话,这个没什么用,不过我们在这里配置一些可能每个Module都有的一些配置,就不用再每个Module中单独去配了,但是不要也是可以的。
好,理解为什么我们的Android工程有这两个文件了吧。因为Android新建项目时默认就是多项目构建。

引入插件:

在Module层的build.gradle文件中:
apply plugin:
(1)App扩展:
apply plugin: ‘android’
apply plugin: ‘com.android.application’
后者是为了遵循Gradle的命名规范而将插件改名,现在都是使用的后者。
(2)Library扩展:com.android.library
(3)Test扩展:com.android.test
还可以引入gradle文件,方式是:
apply from:xx/xxx/xx.xx

Build Script

在Gradle中,因为是约定大于配置,那么什么是约定呢?举个例子,为什么我们Android中项目源码要放在src/main/java中,因为在Android DSL中约定好了,源码就要放这个路径下。
接着看build.gradle文件,android{},这个代码块中就是Android DSL,里面就是设置版本号,签名设置,混淆等。具体的属性和闭包内容很多,下面我列出了部分,想了解对应的使用方法,参见上面给出的官方网址。

Android DSL:
(1) defaultConfig{}
默认配置,可以和flavor配合使用
(2)aaptOptions{}
(3)adbOptions{}
(4)buildTypes{}
Build types 定义一些必须的属性来让Gradle构建和打包你的app。定义在Modle层的build.gradle
(5)compileOptions{}
(6)dataBinding{}
(7)dexOptions{}
(8)jacoco{} JaCoCo 测试覆盖率工具
(9)lintOptions{}
(10)packagingOptions{}
(11)productFlavors{}
(12)signingConfigs{}
(13)sourceSets{}
(14)splits{}
不同apk包含不同的资源和so库
(15)testOptions{}
除了以上15个闭包,还有一部分属性可以直接设置:
1.buildToolsVersion
2.compileSdkVersion
3.defaultPublishConfig
4.flavorDimensionList
5.generatePureSplits
6.ndkDirectory
7.publishNonDefault
8.resourcePrefix
9.sdkDirectory
10.variantFilter

关于Android DSL有几个地方要说一下,首先是buildTypes{}块,这里面的每一个闭包,都会生成与之对应的apk文件,比如我在里面添加

hello{
minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}

那么会生成一个hello版本的apk,同时默认配置了debug和release,就算你什么都不写,也有这两个版本的apk文件。buildTypes{}与productFlavors{}配合使用完成多版本构建。比如我们productFlavors{}这么写:

productFlavors {
        flavor1 {
            versionCode 20
        }

        flavor2 {
            minSdkVersion 14
        }
    }

那么flavor1和flavor2就会与buildTypes中的闭包组合生成多个apk。具体使用可以参考美团文章:http://tech.meituan.com/mt-apk-adaptation.html

Task

看到这你应该对Gradle有一个基本的了解,并且能够配置使用了,但是这还不够,下面的才是重点。Gradle完成一个项目的构建就是通过一个个task。有诱惑力的地方在于我们可以写自己的task,从而完成对构建过程的控制。
通过几步来学习task。
(1)Groovy语法
(2)Gradle命令行操作
(3)在Android Studio中查看并分析task
(4)自定义task并将其加入构建流程

Groovy是轻量级的java,先看环境搭建。

Groovy

1.下载地址:http://groovy-lang.org/download.html
2.下载好后解压,新建环境变量GROOVY_HOME指向解压位置。
3.环境变量PATH后追加%GROOVY_HOME%\bin;
然后打开cmd,输入groovy -v ,如果出现groovy的版本信息,说明环境搭建成功。
GDK自带了一个开发GUI程序,在cmd输入groovyconsole即可出现。
具体的语法这里就不赘述了,网上资料也还比较多。

Gradle

打开cmd,输入gradle -v,这个时候出现了Gradle的版本信息。此时你是不是一脸懵逼,明明我没有安装Gradle的啊,为什么会有Gradle环境呢?因为AS安装后会自动创建Gradle环境,而且这个环境和AS自己编译工程的环境还不一样,坑爹啊,这就导致我一开始通过命令行编译工程一直不对,我还下了好几个版本的Gradle,无语。
它自身编译项目使用的Gradle路径在c/下载/android-studio/gradle/,查看环境变量,将path中的Gradle路径修改为这个路径,这样在命令行中就能正常构建工程了。
\Users\wangliang.gradle 这个是gradle自己设置的目录,里面有配置文件,编译过程中的缓存文件,生成的类文件,编译依赖插件等。

下面我们在命令行来操作一下,打开AS的Terminal窗口,输入gradle projects
可以看到当前只有一个app工程:
这里写图片描述
然后打开AS右侧的Gradle查看当前Gradle的task,这里面的task双击可以运行:
这里写图片描述
接着打开Terminal窗口,输入gradle tasks –all
会显示所有的task,并且后面有该task对应的说明,注意,这里面展示的task和第二步看到的task是一致的,所以我们可以在Terminal窗口查看介绍,然后运行对应的task。

部分任务分析:

1.androidDependencies :展示project的android依赖,包括debug,debugAndroidTest,debugUnitTest,release,releaseUnitTest。
2.signingReport :展示每个版本的签名信息。
3.sourceSets : 展示每个版本的文件位置。
4.assemble:这个task是一个task集合,会将下面这些task全部执行完,它包含了debug和release的assemble。
5.assembleAndroidTest:测试的task集合。
6.build:包含assemble和check两个task集合。
7.buildDependents:同build。
8.buildNeeded:同build。
9.clean :删除构建目录,执行这个task后,project的build目录和module层的build目录都将被删除。
10.compileDebugAndroidTestSources/compileReleaseSouces/compileReleaseUnitTestSources:都是一系列task集合。
11.mockableAndroidJar:创建一个适用于单元测试的android.jar,执行完这一步操作后,会在project层的build文件下的generated里面生成一个jar文件。
12.init,初始化build.gradle文件,如果已经存在就跳过,但是我将build.gradle文件删除后再执行这个task,会报错。(这个问题先留着)
13.wrapper:生成Gradle wrapper文件。
14.installDebug:安装debug版本
15.installDebugAndroidTest:安装debug测试版本
16.check:执行lint和test

17.connectedAndroidTest:安装并运行所有版本的测试。

自定义task并将该task并入构建流程

首先我们定义一个task,很简单就是输出一句helloworld!

class HelloWorldTask extends DefaultTask {
    @Optional
    String message = 'zhangshan'

    @TaskAction
    def hello(){
        println "hello world $message"
    }
}

然后创建该类对应的task:

task hellotask(type:HelloWorldTask){
    message = "i am wangliang"
    it.doLast{
        println 'hhhhhh'
    }
}

@TaskAction表示该Task要执行的动作,即在调用该Task时,hello()方法将被执行。另外,message被标记为@Optional,表示在配置该Task时,message是可选的。
加入后,在右侧的Gradle中就可以找到我们定义的hello了,双击运行,可以看到输出。

看到这你是不是高兴的要蹦起来了,但是我告诉你上面的然并卵呢?上面的task,你需要运行gradle hellotask才能运行,这样肯定是不能加入到Android构建流程中去了,怎么办?
当当当当,看这个方法:

project.afterEvaluate {
    tasks.getByName("preDebugBuild"){
        it.doLast {
            println "hello world !"
        }
    }
}

上面这段代码代表的意思是:在Gradle建立完任务有向图后,执行该Project的afterEvaluate中的方法,然后里面是在preDebugBuild这个task执行完成后输出一句hello world !。
所以,如果我们想影响构建流程,比如在AS自定义的一些task执行过程中加入copy,校验等操作,就通过这种方式。如果是自定义的流程已经预先写好了,那么久通过dependsOn的方式来加入任务。

其他Tips

(1)可以设置task是否可用,方式是hello {}.enabled = true
(2)task依赖的执行顺序不是你写的依赖的先后顺序,而是由task的输入输出规范自动确定的。
(3)Gradle默认处理依赖冲突的方式是选择最新版本。
(4)hello {}.finalizedBy helloX。finalizedBy这个函数相当于java的finally,即使前一个task出错了,后面的这个task仍然会执行。
(5)关于自己写的gradle文件导包的问题,对于build.gradle,可以沿用根目录的build.gradle的配置,但是仅仅限于build.gradle,其他的gradle文件没用,所以需要将根目录build.gradle的配置在自定义的gradle文件中再配置一遍。

总结:基本上完成了对Gradled的学习,掌握了其基本用法和自定义task影响构建流程的方法,但是其API众多,需要加强学习。另外Groovy语法不熟练,在写自定义task的时候会比较慢。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值