Android进阶开发Android开发经验谈互联网科技

【干货篇】Gradle这么差还来面腾讯?

2019-06-14  本文已影响28人  881ef7b85f62

作者:厘米姑娘
在使用Android Studio过程中没少被Gradle坑过,虽然网上有很多简单粗暴的解决方案,但极少会说清楚缘由,所以一直想看一本叫《Android Gradle权威指南》。

不过由于书中实践内容很多,更像一本工具书,而且Gradle现已发行了好几版,因此本篇仅仅是陈列出一些大的要点,尤其是那些熟悉又陌生的名词,如果想要具体了解细节和操作流程,一定要跟着书探索哟~

一. Gradle入门

1.本书环境

JDK:OpenJDK 1.8.0

Gradle:Gradle 2.14.1 All 版

IDE:Android Studio 2.2.3

Android Plugin:Android Gradle 2.2.3

Android:API 23

2.Eclipse和Android Studio

a.开发配置区别:

b.Eclipse迁移到AndroidStudio两种方式:

3.Gradle的ZIP解压后目录

4.引例:Gradle版Hello World

//build.gradle:task hello
{//定义一个任务Task名为hellodoLast{//添加一个动作Action,表示在Task执行完毕后回调doLast闭包中的代码
println'Hello World'//输出字符串,单双号均可
}
}
//终端:
gradle hello//执行build.gradle中名为Hello的任务
//输出:Hello World

5.Gradle Wrapper

a.含义:对Gradle一层包装,便于使用统一Gradle构建

b.目录结构:

|--gradle| |--wrapper|  |--gradle-wrapper.jar|  |--gradle-wrapper.properties|--gradlew|--gradlew.bat

c.常用命令:

6.Gradle日志

a.日志级别:

b.日志输出代码:

c.日志输出控制:

例如,输出QUIET级别及其之上的日志信息:gradle -q tasks

7.Gradle命令行

二.Groovy基础

一句话表明Groovy的地位:Groovy于Gradle,好比Java于Android

1.特性:

Groovy是个灵活的动态脚本语言,语法和Java很相似,又兼容Java,且在此基础上增加了很多动态类型和灵活的特性,如支持闭包和DSL

2.语法

task printStringVar << {def name = "张三”println '单引号的变量计算:${name}'println "双引号的变量计算:${name}"}运行./gradlew printStringVar输出结果:单引号的变量计算:${name}双引号的变量计算:张三
//Listtask printList<<{def numList = [1,2,3,4,5,6];//定义一个Listprintln numList[1]//输出第二个元素println numList[-1]//输出最后一个元素println numList[1..3]//输出第二个到第四个元素numList.each{println it//输出每个元素}}//Maptask printlnMap<<{def map1 =['width':1024,'height':768]//定义一个Mapprintln mapl['width']//输出width的值println mapl.height//输出height的值map1.each{println "Key:${it.key},Value:${it.value}"//输出所有键值对}}
//以集合的each方法为例,接受的参数就是一个闭包numList.each({println it})//省略传参的括号,并调整格式,有以下常见形式numList.each{println it}
task helloJavaBean<<{Person p = new Person()p.name = "张三"println "名字是: ${p.name}"//输出类属性name,为张三println "年龄是: ${p.age}"//输出类属性age,为12}class Person{private String namepublic int getAge(){//省略return12}}
//单个参数task helloClosure<<{customEach{println it}}def customEach(closure){ for(int i in 1..10){ closure(i) }}//多个参数task helloClosure<<{eachMap{k,v-> println "${k} is ${v}" }}def eachMap(closure){def map1 = ["name":"张三","age":18]map1.each{ closure(it.key,it.value) }}

好文推荐:寒冬下2年android的搞笑求职历程 有需要关于Android进阶方面的学习高级技术大纲以及免费教学视频资料的可以私信我【领取资料】哦!

三.Gradle构建脚本基础

1.Settings文件

//添加:app和:common这两个module参与构建include ':app'project(':app').projectDir = new File('存放目录')include':common'project(':common').projectDir = new File('存放目录')

2.Build文件

3.Gradle任务

a.含义:指原子性操作

b.关系:一个Gradle可包含多个Project,一个 Project可包含多个Task,即每个Project是由多个Task组成的;Task是Project的属性,属性名就是任务名

c.创建

def task myTask = task(myTask)myTask.doLast{println "第一种创建Task方法,原型为Task task(String name) throws InvalidUserDataException"}

以任务名+Map创建:Map参数用于对创建的task进行配置,可用配置如下图

def task myTask = task(myTask,group:BasePlugin.BUILD_GROUP)myTask.doLast{println "第二种创建Task方法,原型为Task task(String name,Map<String,?> args) throws InvalidUserDataException"}
task myTask{ doLast{   println "第三种创建Task方法,原型为Task task(String name,Closure configureClosure)" }}

以上创建方式实际上最终都会调用TaskContainter#create()方法,使用./gradlew myTask命令执行任务

d.访问

get方式:tasks.getByPath('路径/名称'),若不存在会抛出UnknownTaskException异常

  **find方式**:tasks.findByPath('路径/名称'),若不存在返回null

get方式:tasks.getByName('名称'),若不存在会抛出UnknownTaskException异常

  **find方式**:tasks.findByName('名称'),若不存在返回null

可见任务名称是唯一的,这是因为TaskContainer的父类 NamedDomainObjectCopllection是个具有唯一不变名字的域对象的集合

e.依赖:在创建任务时通过dependsOn指定其依赖的任务,可以控制任务的执行顺序

task task1<<{println 'hello'}task task2<<{println 'world'}//依赖单个任务task task3(dependsOn:task1){doLast{println 'one'}}//依赖多个任务task task4{dependsOn task1,task2doLast{println 'two'}}

当执行task4时,会发现task1、task2会先执行,再执行task4

注:操作符<< 用在Task定义上相当于doLast

f.排序:除了通过强依赖来控制任务的执行顺序,还可以通过 shouldRunAfter 和 mustRunAfter 实现

taskB.shouldRunAfter(taskA) //表示taskB应该在taskA执行之后执行,有可能不会按预设执行taskB.mustRunAfter(taskA) //表示taskB必须在taskA执行之后执行

g.分组& 描述:分组是对任务的分类,便于归类整理;描述是说明任务的作用;建议两个一起配置,便于快速了解任务的分类和用途

def task myTask = task(myTask)myTask .group = BasePlugin.BUILD_GROUPmyTask .description = '这是一个构建的引导任务'

h.启用 & 禁用:enable属性可以启动和禁用任务,执行被禁用的任务输出提示该任务被跳过

def task myTask = task(myTask)myTask.enable = false //禁用任务

i.执行分析:执行Task的时候实际上是执行其拥有的actions List,它是Task对象实例的成员变量;在创建任务时Gradle会解析其中被TaskAction注解的方法作为其Task执行的action,并添加到 actions List,其中doFirst和doList会被添加到action List第一位和最后一位

4.自定义属性

Project、Task和SourceSet都允许用户添加额外的自定义属性、并对自定义属性进行读取和设置

//给Project添加自定义属性ext.age = 18ext{ phone = 13888888888 address = 'Beijing'}//给Task添加自定义属性task customProperty { ext.inner = 'innnnnner' doLast{ println project.hasProperty('customProperty') //true println project.hasProperty('age') //true println project.hasProperty('inner')//返回fasle println "${age}" println "${phone}" println "${inner}" }}
四.Gradle插件

1.作用

Gradle本身内置许多常用的插件,如若需要还可以扩展现有插件或者自定义插件,如Android Gradle插件就是基于内置的Java插件实现的

2.扩展现有插件

a.插件种类

b.应用插件:通过Project#apply()方法,有三种用法

<一>Map参数:void apply (Map<String, ?> options)如下:

二进制插件:

脚本插件:apply from:'version.gradle'

第三方发布插件:apply plugin:'com.android.application'

注意:应用第三方发布的作为jar的二进制插件时,必须先在buildscript{}配置其classpath才能使用,否则会提示找不到该插件

//buildscript:为项目进行前提准备和初始化相关配置依赖buildscript {repositories {jcenter ()}dependencies {classpath 'com.android.tools.build:gradle:1.5.0"}}apply plugin:'com.android.application

<二>闭包:void apply (Closure closure)

apply { plugin:'java'}

<三>Action:void apply (Action<? super ObjectConfigurationActicn> action)

3.自定义插件:实现Plugin接口、重写apply()方法

五.Java Gradle插件

1.项目结构

使用Java插件要先应用进来:

apply plugin:'java'

此时会添加许多默认设置和约定,比如有以下默认项目结构:

|-example| |-build.gradle| |-src|  |-main|   |-java 源代码存放目录|   |-resources 打包文件存放目录| |-test|  |-java 单元测试用例存放目录|  |-resources 单元测试中使用的文件

2.源集(SourceSet)

比如,在上述Java插件默认项目结构中的main和test就是内置的两个源集,现在更改main源集的Java源文件的存放目录到src/java下:

apply plugin:'java'sourceSets{ main{  java{   srcDir 'src/java'  } }}
apply plugin:'java'sourceSets{ vip{ }}

此时会新建两个目录:src/vip/java和src/vip/resources

补充:除了SourceSet,Java插件里常用的其他属性:

3.配置第三方依赖

a.依赖方式

b.具体方法

举例:

apply plugin:'java'repositories {//外部依赖 依赖Maven中心库maveCentral() }dependencies { //外部依赖 完整写法 compile group:'com.squareup.okhttp3',name:'okhttp', version:'3.0.1'  //外部依赖 简单写法 compile 'com.squareup.okhttp3:okhttp:3.0.1'  //外部依赖 指定main源集依赖 mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'  //项目依赖 compile project(':example')  //文件依赖 依赖libs下两个Jar包 compile files('libs/example01.jar', 'libs/example02.jar')  //文件依赖 指定依赖libs下所有Jar包 compile fileTree(dir: 'libs',include: '*.jar')}

4.内置任务

常用几种任务:

还有些通用任务、对源集适用的任务:

5.多项目构建

//settings.gradleinclude ':app'project(':app').projectDir = new File('存放目录')include ':base'project(':base').projectDir = new File('存放目录')//app/build.gradleapply plugin:'java'dependencies {compile project(':base') }

6.发布构件

//以发布jar构件为例apply plugin:'java 'task publishJar(type:Jar)artifacts{ archives publishJar}uploadArchives{repositories{//发布到本地目录flatDir{ name 'libs' dirs "$projectDir/libs"}//发布到本地Maven库mavenLocal() }}

(未完待续......)

上一篇 下一篇

猜你喜欢

热点阅读