我們在上篇文章《Android Gradle使用詳解(一) 之 Gradle基礎》中介紹了一些關于Gradle的入門相關知識點。本文中會在此基礎上對Android工程中Gradle的相關知識進行進一步學習。
1 項目結構
我們在通過Android Studio建立一個APP工程時,目錄結構如下:
可以看到工程目錄中會自動生成一些檔案。其中可以看到一些我們熟悉的檔案,因為它們跟我們在上篇文章中的Hello World生成的是一樣的。有.gradle檔案夾、gradle檔案夾、build.gradle檔案、gradlew檔案、 gradlew.bat檔案 以及未見過的Settings檔案。我們現在就來一步步分析Android Studio建立工程後Gradld的相關知識點。
1.1 Settings檔案
在Gradle中,根目錄定義了一個設定檔案Settings,它是用于初始化以及工程樹的配置檔案。簡單說就是為了配置工程的子工程,在Android Studio中就是配置Project和Module。可以看到,我們在剛建立的APP工程New Project後Settings檔案隻是簡單的一行代碼:
include ':app'
若再執行New Model後,Settings檔案會自動變成這樣:
include ':app', ':mylibrary'
是以,一個子工程隻有在Settings檔案裡配置了Gradle才會識别,才會在建構的時候被包含進去。建立的Model預設是放在跟Project放在根目錄中,倘若需要更改存放位置于根目錄的sub-project檔案平下,也是很簡單,還是更改一下Settings檔案即可,例如:
include ':app', ':mylibrary'
project(':mylibrary').projectDir = new File('sub-project/mylibrary')
或者(此方式會在左邊Project面闆中多出一項sub-project的空的model)
include ':app'
include ':sub-project:mylibrary'
1.2 Build檔案
每個Project都會有一個Build檔案,它是Project建構的入口,正如上篇文章中的Hello World示例一樣。在Android Studio工程中,若存像上述中有app和mylibrary兩個子工程的話,則會出現3個Build檔案,它們分别是Root Project的build.gradle和兩個Child Project的build.gradle。其中Root Project的build.gradle檔案可以對Child Project統一配置,比如應用的插件、依賴的jcenter庫等。例如在Root Project的build.gradle檔案有這樣的配置代碼:
allprojects {
repositories {
google()
jcenter()
}
}
也有存在在Root Project的build.gradle中使用subprojects的情況。allprojects和subprojects的差別在于,allprojects是所有子產品配置,包括自己,而subprojects隻是對Child Project的配置。
2 插件簡介
Gradle本身内置了很多常用的插件像Java插件,Android Gradle插件就是基于内置的Java插件實作的。插件分二進制插件和腳本插件。使用插件前要先通過Project.apply()方法來應用它。
2.1 二進制插件
二進制插件就是實作了org.gradle.api.Plugin接口的插件,它們可以有plugin id,例如應用一個java插件:
apply plugin: 'java'
其中,’java’是Java插件的plugin id,它是唯一的。又例如應用android插件,可以看到Child Project的build.gradle檔案第一行是:
apply plugin: 'com.android.application'
2.2 應用腳本插件
應用腳本插件,其實就是把這個腳本加載進來,它使用的是關鍵字from,後面緊跟的是一個腳本檔案,可以是本地的,也可以是網絡的,如果是網絡上的話要使用HTTP URL。示例:
build.gradle
apply from:'version.gradle'
task hello << {
println "APP version: ${versionName},code:${versionCode}"
}
version.gradle
ext {
versionName = '1.0.0'
versionCode = 100
}
示例中我們把APP的版本号和版本名稱單獨放在一個腳本檔案裡。這樣我們以後每次APP發版本隻需要更改version.gradle檔案即可。
2.3 第三方插件
若是第三方釋出的作為jar的二進制插件,我們在應用時,必須要先在buildscript{}裡配置其classpath才能使用。這個就好比Android Gradle插件,它是屬于第三方插件,它托管在Jcenter上,是以我們可以看到在Root Project的build.gradle檔案發現有這樣的配置代碼:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
}
}
buildscript{}塊是一個在建構項目之前是,為項目進行前期準備和初始化相關配置依賴的地方,配置好所需的依賴後,就可以在Child Project的build.gradle中應用插件,如可見\app\build.gradle中的第一行代碼:
apply plugin: 'com.android.application'
3 Java插件
Android Gradle插件是基于内置的Java插件來實作的第三方插件,是以我們在開始學習Android Gradle插件前,先來了解Java插件。Java插件約定了項目結構,隻有我們遵循這些約定,Java插件才能找到我們的Java類、資源進行編譯、單元測試類等。預設情況下:
src/main/java 源代碼存放目錄
src/main/resources 打包資源檔案存放目錄
src/test/java 單元測試用例存放目錄
src/test/resources 單元測試中使用的檔案
3.1 約定的項目結構
main和test是Java插件内置的兩個源代碼集合,如果想自己添加一個如vip的目錄可以在build腳本裡這麼配置:
apply plugin: ‘java’
sourceSets {
vip {
}
}
添加一個vip的源代碼集合後,我們就可以在src下建立vip/java和vip/resurces目錄來存放vip相關的源代碼和資源檔案。當然預設的檔案目錄其實也可以修改的,例如:
sourceSets {
vip {
java {
srcDirs ‘src/vip2/java’
}
resources.srcDirs = [‘src/ vip2/resources’] // 另外一樣配置寫法
}
}
如果要修改main和test兩個内置的兩個源代碼集合的存放目錄也是可以的,按照上面vip一樣,将其配置一下就可以。
除此之外,SourceSet裡的源集屬性有:
屬性名 | 類型 | 描述 |
name | String | 它是隻讀,比如main |
output.classesDir | File | 該源集編譯後的class檔案目錄 |
output.resourcesDir | File | 編譯後生成的資源目錄 |
compileClasspath | FileCollection | 編譯後源集時所需的classpath |
java | SourceDirectorySet | 該源集的Java源檔案 |
java.srcDirs | Set | 該源集的Java源檔案所在目錄 |
resources | SourceDirectorySet | 該源集的資源檔案 |
resources.srcDirs | Set | 該源集的資源檔案所在目錄 |
3.2 配置第三方依賴
我們在開發過程中,不可避免會依賴很多優秀的開源第三方Jar。要想使用這些第三方依賴,就要提前告訴給Gradle配置好如何找到這些依賴。例如上述提到Android Gradle是第三方插件,在使用前必須在repositories中進行配置,告訴Gradle是要去jcenter庫搜尋。
repositories
repositories {
jcenter()
}
除jcenter庫以外,如若需要引用其它插件或Jar,我們也可以從mavenCentral、ivy、google或者自己搭建的Maven私服庫等中搜尋,例如:
repositories {
jcenter()
maven {
url ‘http://www.xxx.com/’
}
}
dependencies
配置好倉庫後,就可以繼續配置依賴了。還是例如上述提到Android Gradle是第三方插件,在repositories配置後就可使用dependencies來進行依賴配置:
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
//classpath group: 'com.android.tools.build', name: 'gradle', version: '3.0.1'
}
除了classpath,還提供了以下的依賴配置:
implementation ( 原 compile) 編譯時依賴,依賴不可傳遞
api ( 原 compile) 編譯時依賴,依賴可傳遞
compileOnly ( 原 provided) 編譯時依賴,但代碼不能打進包中
runtime 運作時依賴
testImplementation 編譯測試用例時依賴,依賴不可傳遞
testApi 編譯測試用例時依賴,依賴可傳遞
testRuntime 僅僅在測試用例運作時依賴
archives 項目釋出構件(JAR包等)依賴
default 預設依賴配置
3.3 依賴另一個Gradle項目
在項目内部中當Child Project裡的app要依賴另一個module時,一般就會在app的build.gradle檔案中加入以下的配置:
dependencies {
compile project(':mylibrary')
}
如果依賴的是Jar包,則可以這樣:
dependencies {
compile files( ‘libs/test.jar’, ‘libs/test2.jar’ )
}
或者可以依賴整個檔案夾下的所有Jar包:
dependencies {
compile fileTree( dir : ‘libs’, include : ‘*.jar’ )
}
在Android Studio 3.0開始推薦使用implementation取代了compile。它們的差別是implementation是依賴關系不可能傳遞,而compile可以。使用implementation可以降低項目依賴的偶合性和提高安全性。例如,項目中有app、module1、module2三個module,它們的依賴關系是這樣:app依賴module1,module1依賴module2,如果是使用compile依賴的話是可以做到依賴傳遞,但是如果使用implementation的話,依賴傳遞就會失效。
3.4 任務
Java插件為我們内置了很多有用的Task,下面列舉一些通用的任務:
任務名稱 | 類型 | 描述 |
compileJava | JavaCompile | 使用javac編譯Java源檔案 |
processResource | Copy | 把資源檔案拷貝到生成的資源檔案目錄裡 |
classes | Task | 組裝産生的類和資源檔案目錄 |
compileTestJava | JavaCompile | 使用javac編譯Java源檔案 |
processTestResources | Copy | 把測試資源檔案複制到生産的資源檔案目錄裡 |
testClasses | Task | 組裝産生的測試類和相關資源檔案目錄 |
jar | Jar | 組裝Jar檔案 |
Javadoc | Javadoc | 使用javadoc生成Java API文檔 |
test | Test | 使用Junit或TestNG運作單元測試 |
uploadArchives | Upload | 上傳包含Jar的建構,用archives{}閉包配置 |
clean | Delete | 清理建構生成的目錄檔案 |
cleanTaskName | Delete | 删除指寫任務生成的檔案,比如cleanJar删除Jar任務生成的 |
我們在使用Android Studio建立工程後,便能在Root Project的build.gradle中的最後看到clean任務的配置:
task clean(type: Delete) {
delete rootProject.buildDir
}
對于内置的main和test源集 或者 自己新增的源集(像上面示例的vip)也有一些源集任務:
任務名稱 | 類型 | 描述 |
compileXXJava | JavaCompile | 使用javac編譯指寫源集的Java源代碼 |
processXXResources | Copy | 把指寫源集的資源檔案複制到生産檔案下的資源目錄中 |
XXClasses | Task | 組裝給指寫源集的類和資源檔案目錄 |
3.5 屬性
Java插件為我們也内置了很多有用的屬性,這些屬性都被添加到Project中,可以直接使用,比如前面提到的sourceSets,下面列舉一些常用的源集屬性:
屬性名 | 類型 | 描述 |
sourceSets | SourceSetContainer | 該Java項目的源集,可以通路和配置源集 |
sourceCompatibility | JavaVersion | 編譯Java源檔案使用的Java版本 |
targetCompatibility | JavaVersion | 編譯生成的類的Java版本 |
archivesBasenName | String | 打包成Jar或Zip檔案的名字 |
manifest | Manifest | 用于通路或配置manifest清單檔案 |
libsDir | File | 存放生成的類庫目錄 |
distsDir | File | 存放生成的釋出的檔案的目錄 |