Gradle入門及相關總結

Gradle是一款非常優秀的構建系統工具,它的DSL是基於Groovy實現。可以方便通過代碼控制這些DSL達到構建目的,Gradle構建大部分功能是通過插件方式來實現。

1.Gradle入門及Gradle Wrapper:

Wrappe是對Gradle的一層包裝,便於團隊在開發過程中統一Gradle構建版本,避免因爲Gradle構建版本不同意帶來的不必要麻煩。

  •  gradlew和gradlew.bat分別是Linux和window下的可執行腳本,用法跟Gradle原生命令一樣;
  • gradle-wrapper.jar是具體業務邏輯實現的jar包,gradlew最終還是使用Java執行這個jar包來執行相關Gradle操作;
  • gradle-wrapper.properties是配置文件,用於配置使用哪個版本的Gradle等。
distributionBase=GRADLE_USER_HOME     //下載Gradle壓縮包解壓後存儲的主目錄
distributionPath=wrapper/dists        //相對於distributionBase解壓後Gradle壓縮包路徑
zipStoreBase=GRADLE_USER_HOME        //同distributionBase,只不過存放zip壓縮包
zipStorePath=wrapper/dists           //同distributionPath,只不過存放zip壓縮包
//Gradle發行版壓縮包的下載地址
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip

gradle-wrapper.properties是由Wrapper Task生成的,可以自定義配置Wrapper Task來達到配置gradle-wrapper.properties。在build.gradle構建文件中錄入腳本:

task Wrapper(type: Wrapper){
    gradleVersion = '5.4.2'
    distributionBase='GRADLE_USER_HOME'
    distributionPath= 'wrapper/dists'
    zipStoreBase= 'GRADLE_USER_HOME'
    zipStorePath= 'wrapper/dists'
    distributionUrl= 'https://services.gradle.org/distributions/gradle-5.4.1-all.zip'
}
  • 也可以在Gradle腳本中加入日誌信息:logger.info()等日誌級別信息用於調試。

 

2.Groovy基礎:

Groovy是基於JVM虛擬機的一種動態語言,它的語法與Java非常相似,由Java入門Groovy基本沒有任何障礙。Groovy完全兼容Java,又在此基礎上增加了很多動態類型和靈活特性,比如閉包,支持DSL,是一門非常靈活的動態腳本語言。

  • 字符串:單引號和雙引號都可以定義字符串,其中單引號標記是純粹的字符串常量,而雙引號是可以表示表達式中進行運算;
task printStringClass << {
    def str1 = '單引號字符串'
    def str2 = "雙引號字符串"

}
  • 集合:與Java中的相比更加簡潔
task printList << {
    def numList = [1,2,3,4]
    println numList.getClass().getName()
    println numList[2] //訪問第三個元素
    println numList[-1] //訪問最後一個元素
    numList.each {
        println it      //遍歷訪問

    }
}

task printMap << {
    def map1 = ['width':1920,'height':1080]
    println map1.getClass().getName()
    println map1['width']
    map1.each {
        println("key:${it.key},value:${it.value}")
    }
}
  • 方法:Groovy的調用方法時()可以省略,return可以省略當沒有return時就會用最後一句代碼作爲返回值,代碼塊可以作爲參數傳遞;
task invokeMethod << {
    method1 1,2
    method2(3,4)
}

def method1(int a,int b) {
    println(a+b)
}

def method2(int a,int b) {
    if (a > b) {
        a
    }else {
        b
    }
}
  • JavaBean:在Java中訪問和修改JavaBean的屬性,要重複生成getter/setter方法。而Groovy不用;
  • 閉包概念:是一段代碼塊;
task helloClosure << {
    //使用自定義的閉包
    customEeach {
        print it
    }
}

def customEeach(closure) {
    for (int i = 0; i < 10; i++) {
        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)
    }
}
  • 閉包委託:Groovy的閉包有thisObject/owner/delegate三個屬性,當在閉包內調用方法時,由它們來確定使用哪個對象來處理。默認delegate和owner時相等的,但delegate是可以被修改的;
task helloClosure << {
    new Delegate().test {
        println("thisObject:${thisObject.getClass()}")
    }
}

class Delegate {
    def test(Closure<Delegate> closure){
        closure(this)
    }
}
  • DSL(Domain Specific Language):領域特定語言,專門專注特定領域的語言,它在於專,而不是全。Java是一種通用全面語言。

 

3.Gradle構建腳本基礎:

  • Settings文件:用於初始化以及工程樹的配置,設置文件默認文件名爲setting.gradle,放在根目錄的工程下;

設置的大多的作用都是爲了配置子工程,在Gradle中多個工程是通過工程樹表示的。相當於Android Studio看到Project和Module概念一樣。根目錄相當於Android Studio的Project,一個根目錄可以有很多子工程,也就是有很多Module。

  • Build文件:每個Project都會有一個Build文件,該文件是該Project構建入口,可以在這裏針對該Project進行配置,如配置版本/依賴庫/添加入插件等;可在主Build文件設置所有子模塊的配置信息。
subprojects {
    apply plugin:'java'
    repositories{
        jcenter()
    }
}
  • Project以及Tasks:

在Gradle中可以有很多Project,可以定義創建一個Project用於生成jar/也可以定義另外一個Project生成war包等;一個Project就是在業務範圍內,被抽象出來的一個個獨立模塊可以根據項目情況抽象歸類,最後一個個Project組成整個Gradle;

一個Project中又包含很多Tasks,Tasks就是一個操作,一個原子性的操作。

  • 創建Tasks:Tasks是Project對象的一個函數。原型爲 create(String name,Closure configureClosure),第二個參數是一個閉包;
task helloClosure{
    
}
  • 任務依賴:任務之間是可以有依賴關係的,可以控制任務先於哪個任務執行或後於哪個任務執行;在任務創建的時候,可以通過dependsOn指定其依賴的任務;
task helloClosure <<{
    new Delegate().test {
        println("thisObject:${thisObject.getClass()}")
    }
}

task sayHello(dependsOn:helloClosure){

}
  • 任務間通過API控制/交互:

創建一個任務和定義一個變量是一樣的,變量名就是定義的任務名,可以使用任務名通過Tasks中API訪問方法/屬性/或對任務重新配置。

  • 自定義屬性:Project和Tasks都允許添加自定義屬性,要添加自定義屬性通過對應的ext屬性即可實現;相比於局部變量自定義屬性作用域是整個Project;
//自定義一個project的屬性
ext age = 18
//自定義一個project的代碼塊屬性
ext {
    name = '王麻子'
    age = 18
}

 

4.Gradle任務:

  • 多種方式創建任務:

第一種直接以任務名創建任務的方式:

def Task taskOne = task(taskOne)

第二種以任務名字+一個該任務配置的Map對象來創建任務:

def Task taskTwo = task(taskTwo,group: BasePlugin.BUILD_GROUP)

Task參數中Map的可配置項:

配置項 描述 默認值
type 基於存在的Task來創建,和繼承類似 DefultTask
overwrite 是否替換存在的Task,和type配合用 false
dependOn 用於配置任務的依賴 []
action 添加到任務的一個action或閉包 null
decription 用配置任務的描述 null
group 用於配置任務的分組 null

第三種方式以任務名字+閉包配置的方式:

  • 多種方式訪問任務:

第一種直接通過任務名稱訪問和操作該任務;

第二種通過訪問集合的方式訪問創建的任務;

task["taskOne"].properties{
    
}

第三種通過名稱訪問,有get和find兩種方式:

tasks.findByName("taskOne")
  • 任務的分組和描述:
def Task taskOne = task(taskOne)
taskOne.group = BasePlugin.BUILD_GROUP
taskOne.description = "任務的描述"
  • << 操作符號:在Gradle的Task是doLast()方法的短標記形式;
  • 任務的執行分析:當執行任務時,其實就是執行其擁有的actions列表,這個列表保存在Task對象實例中的action成員變量中,類型爲List,一個任務執行方法有doFrist/doSelf/doLast;
  • 任務的排序:通過任務的shouldRunAfter和mustRunAfter兩個方法控制一個任務應該或者必須在另一個任務之後執行;
  • 任務的啓動和禁用:通過enable屬性來設置啓動和禁用,默認爲true;
  • 任務的onlyIf的斷言:是一個表達式,有onlyIf方法接受一個閉包作爲參數,如該閉包返回爲true該任務執行否則跳過;

 

5.Gradle插件:

  • 插件作用:插件會擴展項目的功能,在項目的構建過程中做很多事

可以添加任務到項目中,幫忙完成一些事,如測試/編譯/打包等;

可以添加依賴配置到項目中,如依賴的第三方庫;

可以向項目中現有的對象類型添加新的擴展屬性/方法等,有助於配置/優化構建;

可以對項目進行一些約定。

  • 應用插件:

應用二進制插件,二進制插件就是實現了org.gradle.api.Plugin的插件:

apply plugin: 'org.gradle.api.plugins.JavaPlugin'
  • 應用腳本插件:
apply form: 'version.gradle'
  • apply方法的其他用法:
void apply(Closure closure);
void apply(Action<? super ObjectConfigurationAction> action);
void apply(Map<String, ?> options);

apply {
    plugin 'java'
}
  • 應用第三方發佈的插件,buildscript{}是在構建項目之前,爲項目進行前期準備和初始化相關配置依賴地方,配置好所需的依賴就可以應用插件了:
buildscript {
    repositories {
        google()
        jcenter()       //構建腳本引入jcenter
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}
  • 使用plugin DSL應用插件;
  • 自定義插件:自定義插件必須實現Plugin接口,這個接口只有一個apply方法,該方法在插件被應用時被執行。
class mySelfPlugin implements Plugin<Project> {

    @Override
    void apply(Project target) {

    }
}

 

6.Java Gradle插件:

  • Java插件的運用:
apply plugin:'java'

通過以上腳本的應用之後,Java插件會爲工程添加很多有用的默認設置和約定,如源代碼的位置/單元測試代碼的位置/資源文件的位置等。一般情況下最好遵循它的默認設置。

  • Java插件約定的項目結構:

默認情況下,Java插件約定src/main/java爲我們項目源代碼存放目錄;src/main/resources爲要打包的文件存放目錄如一些Properties配置文件和圖片等;src/test/java爲我們單元測試存放目錄;src/test/resources爲存放單元測試中使用的文件。

也可以新建一個源集,目錄用於存放其他結構的代碼資源,如下:

sourceSets {
    vip{
        
    }
}
  • 配置第三方依賴:
  repositories {
        //配置倉庫
        mavenCentral()
        maven {
            url'http://www.mavenurl.com/'
        }
        
    }
    //配置依賴
  dependencies {
        compile 'com.squareup.okhttp3:okhttp:3.0.1'
       
    }

Gradle提供的配置依賴:

名稱 繼承於 被哪個任務使用 意義
compile _ compileJava 編譯時依賴
runtime compile _ 運行時依賴
testCompile compile compileTestJava 編譯測試用例時依賴
testRuntime runtime testCompile test 僅在測試用例運行時依賴
archive —— uploadArchive 該項目發佈構建(jar包等)依賴
default runtime _ 默認依賴配置

Java插件可以爲不同源集在編譯時和運行時指定不同的依賴。

dependencies {
        mainCompile 'com.squareup.okhttp3:okhttp:3.0.1'
        VIPCompile 'com.squareup.okhttp3:okhttp:2.5.1'
    }

依賴通用使用格式:

名稱 繼承於 被哪個任務使用 意義
sourceSetCompile _ sourceSetCompileJava 爲指定源集提供編譯時依賴
sourceSetRuntime sourceSetCompile _ 爲指定源集提供運行時依賴

項目依賴:

dependencies {
        compile project('項目名稱')    //項目名在同一目錄下
        compile files('lib/項目名稱')   //項目名在同一下lib目錄下
        compile fileTree(dir:'libs',include:'*.jar')    //包含所有libs,後綴爲.jar文件
    }
  • 源碼集合(sourceSet)概念:是Java插件用來描述和管理代碼及資源的一個抽象概念,是一個Java源代碼文件和資源文件的集合。通過源集,可以方便地訪問源代碼目錄,設置源集屬性,更改源集的Java目錄或者資源目錄等;有了源集可以針對不同的業務和應用對源代碼進行分組。

Java插件在Project下爲我們提供了一個sourceSet屬性以及一個sourceSet{}閉包來訪問和配置源集。

常用源集屬性:

屬性名 類型 描述
name String 它是隻讀的,如main
output.classesDir File 該源集編譯後的class文件目錄
output.resourcesDir File 編譯後生成的資源目錄
compileClasspath FileCollection 編譯該源集時所需的classpath
java SourceDirectorySet 該源集的Java源文件
java.srcDir Set 該源集Java源文件所在目錄
resources SourceDirectorySet 該源集的資源文件
resources.srcDir Set 該源集的資源文件所在目錄

 

  • Java插件添加的任務:

Java插件添加的通用任務:

任務名稱 類型 描述
compileJava JavaCompile 使用javac編譯Java源文件
processResources Copy 把資源文件拷貝到生產的資源目錄裏
classes Task 組裝生產的類和資源文件目錄
compileTestJava JavaCompile 使用javac測試Java源文件
processTestResources Copy 把測試資源文件拷貝到生產的資源目錄裏
testClasses Task 組裝生產的測試類和相關資源文件目錄
jar Jar 組裝Jar文件
test Test 使用JUnit或TestNG運行單元測試
uploadArchives Upload 上傳包含jar的構建,使用archive{}閉包配置
clean Delete 清除構建生成的目錄文件
cleanTaskName Delete 刪除指定任務生成的文件,
javacdoc Jar 使用javacdoc生成Java API文檔

源集任務:

任務名稱 類型 描述
compileSourcesJava JavaCompile 使用javac編譯指定源集的Java源代碼
processSourcesSetResources Copy 把指定源集的資源文件複製到生產文件下的資源目錄中
sourceSetClasses Task 組裝給定源集的類和資源文件目錄
  • Java插件添加的屬性:

Java插件添加了很多常用的屬性,這些屬性都被添加到Project中,可以直接使用;

Java插件添加屬性的源集屬性:

屬性名 類型 描述
sourcesSet SourcesSetContainer 該Java項目的源集,可以訪問和配置源集
sourcesCompatibility JavaVersion 編譯Java源文件使用的Java版本
targetCompatibility JavaVersion 編譯生成的類的Java版本
archiveBaseName String 打包jar或zip文件的名稱
manifest Manifest 用於訪問或配置的manifest清單文件
libDir File 存放生成的類庫目錄
distsDir File 存放生成的發佈的文件的目錄
  • 多項目構建:

多項目構建,其實就是多個Gradle項目一起構建,一起通過Settings.gradle配置管理。每個項目下都有一個build文件對該項目進行配置,然後採用項目依賴就可以實現多個項目協作。

  • 發佈構件:Gradle構建的產物,稱之爲構件;一個構件就是一個jar,也可以是一個zip包或war包;發佈構件是通過artifacts{}閉包配置的;uploadArchives是一個Upload Task,用上傳發布構件。
apply plugin: 'java'

task publishJar(type: Jar)

artifacts {
    archives publishJar
}

uploadArchives{
    repositories{
        flatDir{
            name 'libs'
            dir '$projectDir/libs'
        }
        mavenCentral()
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章