ant构建项目迁移到gradle_Gradle这么弱还跑来面腾讯?
?多點(diǎn)在看,就是真愛
作者:?厘米姑娘(騰訊開發(fā)妹子)| 來源 :公號(hào) 碼個(gè)蛋
https://www.jianshu.com/p/1274c1f1b6a4
前言
在使用Android Studio過程中沒少被Gradle坑過,雖然網(wǎng)上有很多簡(jiǎn)單粗暴的解決方案,但極少會(huì)說清楚緣由,所以一直想看一本叫《Android Gradle權(quán)威指南》。
不過由于書中實(shí)踐內(nèi)容很多,更像一本工具書,而且Gradle現(xiàn)已發(fā)行了好幾版,因此本篇僅僅是陳列出一些大的要點(diǎn),尤其是那些熟悉又陌生的名詞,如果想要具體了解細(xì)節(jié)和操作流程,一定要跟著書探索喲~
Gradle入門
Groovy基礎(chǔ)
Gradle構(gòu)建腳本基礎(chǔ)
Gradle插件
Java Gradle插件
Android Gradle插件
一. Gradle入門
1.本書環(huán)境
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.開發(fā)配置區(qū)別:
Eclipse+ADT+Ant
Android Studio+Gradle:Gradle比Ant更靈活,有效提高開發(fā)效率
b.Eclipse遷移到AndroidStudio兩種方式:
使用AndroidStudio直接導(dǎo)入Eclipse工程
? ? ??特點(diǎn):使用AS默認(rèn)推薦目錄結(jié)構(gòu)
使用Eclipse導(dǎo)出Android Gradle配置文件,并轉(zhuǎn)換成Gradle工程,再使用Android Studio把它作為Gradle工程導(dǎo)入
? ? ? 特點(diǎn):保留原項(xiàng)目結(jié)構(gòu)
3.Gradle的ZIP解壓后目錄
docs:API、 DSL、指南等文檔
init.d:gradle初始化腳本目錄
lib:相關(guān)庫(kù)
media:一些icon資源
samples:示例
src:源文件
getting-started.html:入門鏈接
LICENSE
NOTICE
4.引例:Gradle版Hello World
//build.gradle:task hello{//定義一個(gè)任務(wù)Task名為hello
doLast{//添加一個(gè)動(dòng)作Action,表示在Task執(zhí)行完畢后回調(diào)doLast閉包中的代碼
println'Hello World'//輸出字符串,單雙號(hào)均可
}
}
//終端:
gradle hello//執(zhí)行build.gradle中名為Hello的任務(wù)
//輸出:
Hello World
5.Gradle Wrapper
a.含義:對(duì)Gradle一層包裝,便于使用統(tǒng)一Gradle構(gòu)建
b.目錄結(jié)構(gòu):
|--gradle| |--wrapper
|? |--gradle-wrapper.jar
|? |--gradle-wrapper.properties
|--gradlew
|--gradlew.bat
gradle-wrapper.jar:具體業(yè)務(wù)邏輯實(shí)現(xiàn)的jar包
gradle-wrapper.properties:配置文件,包含篇配置信息如下圖:
gradlew:Linux下可執(zhí)行腳本
gradlew.bat:Windows下可執(zhí)行腳本
c.常用命令:
生成:gradle wrapper,由Wrapper Task生成
配置參數(shù):
????????- gradle wrapper --gradle-version XXX用于指定使用的Gradle版本
? ? ????- gradle wrapper --distribution-url XXX用于指定下載Gradle發(fā)行版的url地址
自定義:task wrapper(type:Wrapper){ //配置信息 }
6.Gradle日志
a.日志級(jí)別:
b.日志輸出代碼:
使用print方法,屬于quiet級(jí)別日志:println 'XX'X
使用內(nèi)置logger:
c.日志輸出控制:
例如,輸出QUIET級(jí)別及其之上的日志信息:gradle -q tasks
7.Gradle命令行
查看所有可執(zhí)行tasks:./gradlew tasks
強(qiáng)制刷新依賴:./gradlew --refresh-dependencies assemble
多任務(wù)調(diào)用:./gradlew clean jar
查看幫助:./gradlew -?或./gradlew -h或./gradlew -help
二.Groovy基礎(chǔ)
一句話表明Groovy的地位:Groovy于Gradle,好比Java于Android1.特性:
Groovy是個(gè)靈活的動(dòng)態(tài)腳本語言,語法和Java很相似,又兼容Java,且在此基礎(chǔ)上增加了很多動(dòng)態(tài)類型和靈活的特性,如支持閉包和DSL
2.語法
分號(hào)不必需
字符串:單引號(hào)和雙引號(hào)均可定義一個(gè)字符串常量,區(qū)別在于單引號(hào)不能對(duì)字符串表達(dá)式做運(yùn)算,而雙引號(hào)可以
def name = "張三”
println '單引號(hào)的變量計(jì)算:${name}'
println "雙引號(hào)的變量計(jì)算:${name}"
}
運(yùn)行./gradlew printStringVar輸出結(jié)果:
單引號(hào)的變量計(jì)算:${name}
雙引號(hào)的變量計(jì)算:張三
集合:以List和Map為例,介紹如何定義集合和訪問集合元素
task printList< def numList = [1,2,3,4,5,6];//定義一個(gè)List
println numList[1]//輸出第二個(gè)元素
println numList[-1]//輸出最后一個(gè)元素
println numList[1..3]//輸出第二個(gè)到第四個(gè)元素
numList.each{
println it//輸出每個(gè)元素
}
}
//Map
task printlnMap< def map1 =['width':1024,'height':768]//定義一個(gè)Map
println mapl['width']//輸出width的值
println mapl.height//輸出height的值
map1.each{
println "Key:${it.key},Value:${it.value}"//輸出所有鍵值對(duì)
}
}
方法:方法調(diào)用傳參的括號(hào)可省略;return不必需,無return時(shí)會(huì)將最后一行代碼作為其返回值;允許將代碼塊(閉包)作為參數(shù)傳遞
numList.each({println it})
//省略傳參的括號(hào),并調(diào)整格式,有以下常見形式
numList.each{
println it
}
不是一定要定義成員變量才能作為類屬性被訪問,用get/set方法也能當(dāng)作類屬性
p.name = "張三"
println "名字是: ${p.name}"//輸出類屬性name,為張三
println "年齡是: ${p.age}"//輸出類屬性age,為12
}
class Person{
private String namepublic int getAge(){//省略return
12
}
}
閉包:當(dāng)閉包有一個(gè)參數(shù)時(shí),默認(rèn)為it,多個(gè)參數(shù)時(shí)需要一一羅列
task helloClosure< customEach{
println it
}
}
def customEach(closure){
?for(int i in 1..10){
?closure(i)
?}
}
//多個(gè)參數(shù)
task helloClosure< eachMap{k,v->
?println "${k} is ${v}"
?}
}
def eachMap(closure){
def map1 = ["name":"張三","age":18]
map1.each{
?closure(it.key,it.value)
?}
}
三.Gradle構(gòu)建腳本基礎(chǔ)
1.Settings文件
作用:初始化、設(shè)置工程樹
文件名:settings.gradle,放在Project下
常用方法:include方法指定能被Gradle識(shí)別的Module
include ':app'
project(':app').projectDir = new File('存放目錄')
include':common'
project(':common').projectDir = new File('存放目錄')
2.Build文件
Project的build.gradle:整個(gè)Project的共有屬性,包括配置版本、插件、依賴庫(kù)等信息
Module的build.gradle:各個(gè)module私有的配置文件
3.Gradle任務(wù)
a.含義:指原子性操作
b.關(guān)系:一個(gè)Gradle可包含多個(gè)Project,一個(gè) Project可包含多個(gè)Task,即每個(gè)Project是由多個(gè)Task組成的;Task是Project的屬性,屬性名就是任務(wù)名
c.創(chuàng)建
以任務(wù)名創(chuàng)建:接受一個(gè)name參數(shù)
myTask.doLast{
println "第一種創(chuàng)建Task方法,原型為Task task(String name) throws InvalidUserDataException"
}
以任務(wù)名+Map創(chuàng)建:Map參數(shù)用于對(duì)創(chuàng)建的task進(jìn)行配置,可用配置如下圖
def task myTask = task(myTask,group:BasePlugin.BUILD_GROUP)myTask.doLast{
println "第二種創(chuàng)建Task方法,原型為Task task(String name,Map args) throws InvalidUserDataException"
}
以任務(wù)名+閉包創(chuàng)建:常見形式
?doLast{
? ?println "第三種創(chuàng)建Task方法,原型為Task task(String name,Closure configureClosure)"
?}
}
以上創(chuàng)建方式實(shí)際上最終都會(huì)調(diào)用TaskContainter#create()方法,使用./gradlew myTask命令執(zhí)行任務(wù)
d.訪問
通過任務(wù)名訪問:名稱.方法
通過TaskContainter訪問:tasks['名稱'].方法
通過路徑訪問:參數(shù)可以為路徑或名稱
? ?get方式:tasks.getByPath('路徑/名稱'),若不存在會(huì)拋出UnknownTaskException異常
? ? ??find方式:tasks.findByPath('路徑/名稱'),若不存在返回null
通過名稱訪問:參數(shù)只能為名稱
? get方式:tasks.getByName('名稱'),若不存在會(huì)拋出UnknownTaskException異常
? ? ??find方式:tasks.findByName('名稱'),若不存在返回null
可見任務(wù)名稱是唯一的,這是因?yàn)門askContainer的父類 NamedDomainObjectCopllection是個(gè)具有唯一不變名字的域?qū)ο蟮募?/p>
e.依賴:在創(chuàng)建任務(wù)時(shí)通過dependsOn指定其依賴的任務(wù),可以控制任務(wù)的執(zhí)行順序
task task1< println 'hello'}
task task2< println 'world'
}
//依賴單個(gè)任務(wù)
task task3(dependsOn:task1){
doLast{
println 'one'
}
}
//依賴多個(gè)任務(wù)
task task4{
dependsOn task1,task2
doLast{
println 'two'
}
}
當(dāng)執(zhí)行task4時(shí),會(huì)發(fā)現(xiàn)task1、task2會(huì)先執(zhí)行,再執(zhí)行task4
注:操作符<< 用在Task定義上相當(dāng)于doLastf.排序:除了通過強(qiáng)依賴來控制任務(wù)的執(zhí)行順序,還可以通過 shouldRunAfter 和 mustRunAfter 實(shí)現(xiàn)
taskB.shouldRunAfter(taskA) //表示taskB應(yīng)該在taskA執(zhí)行之后執(zhí)行,有可能不會(huì)按預(yù)設(shè)執(zhí)行taskB.mustRunAfter(taskA) //表示taskB必須在taskA執(zhí)行之后執(zhí)行
g.分組& 描述:分組是對(duì)任務(wù)的分類,便于歸類整理;描述是說明任務(wù)的作用;建議兩個(gè)一起配置,便于快速了解任務(wù)的分類和用途
def task myTask = task(myTask)myTask .group = BasePlugin.BUILD_GROUP
myTask .description = '這是一個(gè)構(gòu)建的引導(dǎo)任務(wù)'
h.啟用 & 禁用:enable屬性可以啟動(dòng)和禁用任務(wù),執(zhí)行被禁用的任務(wù)輸出提示該任務(wù)被跳過
def task myTask = task(myTask)myTask.enable = false //禁用任務(wù)
i.執(zhí)行分析:執(zhí)行Task的時(shí)候?qū)嶋H上是執(zhí)行其擁有的actions List,它是Task對(duì)象實(shí)例的成員變量;在創(chuàng)建任務(wù)時(shí)Gradle會(huì)解析其中被TaskAction注解的方法作為其Task執(zhí)行的action,并添加到 actions List,其中doFirst和doList會(huì)被添加到action List第一位和最后一位
4.自定義屬性
Project、Task和SourceSet都允許用戶添加額外的自定義屬性、并對(duì)自定義屬性進(jìn)行讀取和設(shè)置
方式:通過ext屬性,添加多個(gè)通過ext代碼塊
優(yōu)點(diǎn):相比局部變量有廣泛的作用域,可以跨Project、跨Task訪問,只要能訪問這些屬性所屬的對(duì)象即可
ext.age = 18
ext{
?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.作用
可以添加任務(wù)到項(xiàng)目,比如測(cè)試、編譯、打包等
可以添加依賴配置到項(xiàng)目,幫助配置項(xiàng)目構(gòu)建過程中需要的依賴,比如第三方庫(kù)等
可以向項(xiàng)目中現(xiàn)有的對(duì)象類型添加新的擴(kuò)展屬性和方法等,幫助配置和優(yōu)化構(gòu)建
可以對(duì)項(xiàng)目進(jìn)行一些約定,比如約定源代碼存放位置等
Gradle本身內(nèi)置許多常用的插件,如若需要還可以擴(kuò)展現(xiàn)有插件或者自定義插件,如Android Gradle插件就是基于內(nèi)置的Java插件實(shí)現(xiàn)的
2.擴(kuò)展現(xiàn)有插件
a.插件種類
二進(jìn)制插件:實(shí)現(xiàn)org.gradle.api.Plugin接口的插件,可以有plugin id
腳本插件:嚴(yán)格上只是一個(gè)腳本,可以來自本地或網(wǎng)路
b.應(yīng)用插件:通過Project#apply()方法,有三種用法
Map參數(shù):void apply (Map options)如下:
二進(jìn)制插件:
id:apply plugin:'java'
類型:apply plugin:org.gradle.api.plugins.JavaPlugin
簡(jiǎn)寫:apply plugin:JavaPlugin
腳本插件:apply from:'version.gradle'
第三方發(fā)布插件:apply plugin:'com.android.application'
注意:應(yīng)用第三方發(fā)布的作為jar的二進(jìn)制插件時(shí),必須先在buildscript{}配置其classpath才能使用,否則會(huì)提示找不到該插件//buildscript:為項(xiàng)目進(jìn)行前提準(zhǔn)備和初始化相關(guān)配置依賴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.自定義插件:實(shí)現(xiàn)Plugin接口、重寫apply()方法
五.Java Gradle插件
1.項(xiàng)目結(jié)構(gòu)
使用Java插件要先應(yīng)用進(jìn)來:
apply plugin:'java'此時(shí)會(huì)添加許多默認(rèn)設(shè)置和約定,比如有以下默認(rèn)項(xiàng)目結(jié)構(gòu):
|-example| |-build.gradle
| |-src
|??|-main
|? ?|-java 源代碼存放目錄
|? ?|-resources 打包文件存放目錄
| |-test
|??|-java 單元測(cè)試用例存放目錄
|??|-resources 單元測(cè)試中使用的文件
2.源集(SourceSet)
作用:用于描述和管理源代碼(java)及其資源(resources),如訪問源代碼目錄、設(shè)置源集屬性、更改Java原代碼目錄等
方式:通過sourceSets屬性(是一個(gè)SourceSetsContainer)和sourceSets{}閉包
常用屬性:
比如,在上述Java插件默認(rèn)項(xiàng)目結(jié)構(gòu)中的main和test就是內(nèi)置的兩個(gè)源集,現(xiàn)在更改main源集的Java源文件的存放目錄到src/java下:
apply plugin:'java'sourceSets{
?main{
? java{
? ?srcDir 'src/java'
? }
?}
}
定義新源集:通過sourceSets{}閉包添加
sourceSets{
?vip{
?}
}
此時(shí)會(huì)新建兩個(gè)目錄:src/vip/java和src/vip/resources
補(bǔ)充:除了SourceSet,Java插件里常用的其他屬性:
3.配置第三方依賴
a.依賴方式
外部依賴:依賴外部倉(cāng)庫(kù),如Maven、Ivy等
項(xiàng)目依賴:依賴項(xiàng)目,依賴后可以使用該項(xiàng)目的Java類
文件依賴:如依賴Jar包,出于安全考慮不發(fā)布到Maven而是放在項(xiàng)目的libs文件夾下
b.具體方法
對(duì)于外部依賴,需要先在repositories{}閉包里聲明依賴庫(kù)的位置
在dependencies{}閉包添加依賴
????????- 外部依賴:說明依賴庫(kù)的group:name:version
????????-?項(xiàng)目依賴:project('項(xiàng)目名稱')
????????-?文件依賴:files('文件名稱'),多個(gè)文件逗號(hào)分開,或者fileTree(dir:'文件名稱',include:'*.擴(kuò)展名稱')依賴指定文件夾下指定擴(kuò)展名文件
幾種依賴類型
舉例:
apply plugin:'java'repositories {
//外部依賴 依賴Maven中心庫(kù)
maveCentral()
}
dependencies {
?//外部依賴 完整寫法
?compile group:'com.squareup.okhttp3',name:'okhttp', version:'3.0.1'
?//外部依賴 簡(jiǎn)單寫法
?compile 'com.squareup.okhttp3:okhttp:3.0.1'
?//外部依賴 指定main源集依賴
?mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'
?//項(xiàng)目依賴
?compile project(':example')
?//文件依賴 依賴libs下兩個(gè)Jar包
?compile files('libs/example01.jar', 'libs/example02.jar')
?//文件依賴 指定依賴libs下所有Jar包
?compile fileTree(dir: 'libs',include: '*.jar')
}
4.內(nèi)置任務(wù)
常用幾種任務(wù):
build任務(wù):構(gòu)建項(xiàng)目
clean任務(wù):刪除build目錄及構(gòu)建生成的文件
assemble任務(wù):不執(zhí)行單元測(cè)試,只編譯和打包
check任務(wù):只執(zhí)行單元測(cè)試
javadoc任務(wù):生成Java格式的doc api文檔
還有些通用任務(wù)、對(duì)源集適用的任務(wù):
5.多項(xiàng)目構(gòu)建
含義:多個(gè)Gradle項(xiàng)目一起構(gòu)建
方式:通過settings.gradle配置管理多項(xiàng)目;在每個(gè)項(xiàng)目都有一個(gè)build.gradle,采用項(xiàng)目依賴就能實(shí)現(xiàn)多項(xiàng)目協(xié)作
include ':app'
project(':app').projectDir = new File('存放目錄')
include ':base'
project(':base').projectDir = new File('存放目錄')
//app/build.gradle
apply plugin:'java'
dependencies {
compile project(':base')
}
6.發(fā)布構(gòu)件
構(gòu)件:Gradle構(gòu)建的產(chǎn)物,如Jar包、Zip包等
意義:發(fā)布構(gòu)建給其他工程使用,可以發(fā)布到本地目錄、Maven、Ivy等
方式:明確構(gòu)件類型,并通過artifacts{}閉包配置需要發(fā)布的構(gòu)建,在uploadArchives{}上傳發(fā)布構(gòu)件
apply plugin:'java '
task publishJar(type:Jar)
artifacts{
?archives publishJar
}
uploadArchives{
repositories{
//發(fā)布到本地目錄
flatDir{
?name 'libs'
?dirs "$projectDir/libs"
}
//發(fā)布到本地Maven庫(kù)
mavenLocal()
?}
}
篇幅有限,更多請(qǐng)閱讀作者妹子的博文:
https://www.jianshu.com/p/1274c1f1b6a4
---------? END? ----------
推薦閱讀
Android系統(tǒng)服務(wù)(一)解析ActivityManagerService(AMS)
Android PMS的創(chuàng)建過程
美團(tuán)跨平臺(tái)框架Picasso,開啟大前端的未來
徹底理解cookie、session、token
你好,我是劉望舒,十年經(jīng)驗(yàn)的資深架構(gòu)師,著有兩本業(yè)界知名的技術(shù)暢銷書。
如果你喜歡我的文章,就給公眾號(hào)加個(gè)星標(biāo)吧,方便閱讀。
推薦一個(gè)可以讓你技術(shù)快速提升的神奇地方,有興趣的同學(xué)可以點(diǎn)擊底部的?閱讀原文?
??在看也是一種認(rèn)可
總結(jié)
以上是生活随笔為你收集整理的ant构建项目迁移到gradle_Gradle这么弱还跑来面腾讯?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: atcg分别是什么 atcg分别指什么东
- 下一篇: markdown 行内公式_如何轻松将笔