Gradle系列(二) Gradle執行順序和task

0. 前情提示

Gradle系列已完成,專一於Gradle,有以下幾篇文章html

1. 什麼是gradle

維基百科:Gradle是一個基於Apache Ant和Apache Maven概念的項目自動化建構工具。它使用一種基於Groovy的特定領域語言來聲明項目設置,而不是傳統的XML。當前其支持的語言限於Java、Groovy和Scala,計劃將來將支持更多的語言。java

按個人理解,通俗一點講,就是拿來構建項目的,咱們平時在Android Studio上開發Android項目就是用Gradle進行構建的,相比於傳統的xml方式,我感受更加靈活.畢竟,能夠寫代碼,根據不一樣的環境搞些騷操做.linux

gradle裏面其實須要學習的有3個android

剛哥說過,遇到不會的直接查官方文檔,不要每次去搜索引擎東搜西搜,這樣效率很低.git

這裏插播一個小知識點,如何查詢官方文檔.好比在gradle中常常用的buildscript究竟是什麼?來到官方文檔首頁,點開頂部INDEX,搜索buildscript,便可找到這個東西是解釋.github

2. gradle項目結構

首先咱們來新建一個Android項目,什麼都不要動.spring

QZLQBT.png

  • 最外層setting.gradle爲根項目的配置,能夠知道須要包含哪些模塊,而後最外層的build.gralde也是根項目的配置.模塊中的build.gradle是子項目的配置.
  • gradle文件夾下面是版本配置以及gradle所須要的腳本
  • 最外層的gradlew爲linux/mac下的腳本,gradlew.bat是windows下面用的腳本

3. gradle配置順序

簡單在gradle中輸出語句,看看配置順序windows

//settings.gradle
println("setting 開始配置")
include ':app'
rootProject.name='Hello'
println("setting 配置完成")
複製代碼
//project build.gradle
println("根build.gradle 開始配置")
buildscript {
    repositories {
    }
    dependencies {
    }
}
println("根build.gradle 配置完成")
複製代碼
//app build.gradle
println("app build.gradle 開始配置")

project.afterEvaluate {
    println "全部模塊都已配置完成"
}

android {
    defaultConfig {
    }
    buildTypes {
    }
}

dependencies {
}
println("app build.gradle 配置完成")
複製代碼

打印語句寫好後,clean Project,便可執行,輸出以下:api

setting 開始配置
setting 配置完成

> Configure project :
根build.gradle 開始配置
根build.gradle 配置完成

> Configure project :app
app build.gradle 開始配置
app build.gradle 配置完成
全部模塊都已配置完成
複製代碼

能夠看到首先是配置setting,知道有哪些模塊.而後是配置根項目的build.gradle,而後纔是子項目的build.gradle配置.bash

我在上面加了一個監聽器project.afterEvaluate,能夠經過查詢官方文檔瞭解它的詳細內容,這是一個當全部的模塊都配置完了的時候的回調.

其中,還能夠在settings.gradle中添加一個監聽器

gradle.addBuildListener(new BuildListener() {
    @Override
    void buildStarted(Gradle gradle) {
        println("buildStarted------------")
    }

    @Override
    void settingsEvaluated(Settings settings) {
        println("settingsEvaluated------------")
    }

    @Override
    void projectsLoaded(Gradle gradle) {
        println("projectsLoaded------------")
    }

    @Override
    void projectsEvaluated(Gradle gradle) {
        println("projectsEvaluated------------")
    }

    @Override
    void buildFinished(BuildResult result) {
        println("buildFinished------------")
    }
})
複製代碼

在執行構建的時候,這個監聽器會監聽到主要的生命週期事件,看名字大概就能大概猜出是什麼意思,buildStarted已過期.也能夠看看官方文檔詳細瞭解

加入以後打印以下:

setting 開始配置
setting 配置完成
settingsEvaluated------------
projectsLoaded------------

> Configure project :
根build.gradle 開始配置
根build.gradle 配置完成

> Configure project :app
app build.gradle 開始配置
app build.gradle 配置完成
全部模塊都已配置完成
projectsEvaluated------------

buildFinished------------
複製代碼

4. gradle task

4.1 初識task

gradle中全部的構建工做都是由task完成的,它幫咱們處理了不少工做,好比編譯,打包,發佈等都是task.咱們能夠在項目的根目錄下,打開命令行(AS自帶,底部有Terminal,打開就行)執行gradlew tasks查看當前項目全部的task.

在命令行若是執行失敗,則將項目的JDK location設置成本地jdk的路徑,並且jdk的版本還須要是java 8. 我用的jdk版本是1.8.0_231.

> Task :tasks

------------------------------------------------------------
Tasks runnable from root project
------------------------------------------------------------

Android tasks
-------------
androidDependencies - Displays the Android dependencies of the project.
signingReport - Displays the signing info for the base and test modules
sourceSets - Prints out all the source sets defined in this project.

Build tasks
-----------
assemble - Assemble main outputs for all the variants.
assembleAndroidTest - Assembles all the Test applications.
build - Assembles and tests this project.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildNeeded - Assembles and tests this project and all projects it depends on.
bundle - Assemble bundles for all the variants.
clean - Deletes the build directory.
cleanBuildCache - Deletes the build cache directory.
compileDebugAndroidTestSources
compileDebugSources
compileDebugUnitTestSources
compileReleaseSources
compileReleaseUnitTestSources

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Cleanup tasks
-------------
lintFix - Runs lint on all variants and applies any safe suggestions to the source code.

Help tasks
----------
buildEnvironment - Displays all buildscript dependencies declared in root project 'Hello'.
components - Displays the components produced by root project 'Hello'. [incubating]
dependencies - Displays all dependencies declared in root project 'Hello'.
dependencyInsight - Displays the insight into a specific dependency in root project 'Hello'.
dependentComponents - Displays the dependent components of components in root project 'Hello'. [incubating]
help - Displays a help message.
model - Displays the configuration model of root project 'Hello'. [incubating]
projects - Displays the sub-projects of root project 'Hello'.
properties - Displays the properties of root project 'Hello'.
tasks - Displays the tasks runnable from root project 'Hello' (some of the displayed tasks may belong to subprojects).

Install tasks
-------------
installDebug - Installs the Debug build.
installDebugAndroidTest - Installs the android (on device) tests for the Debug build.
uninstallAll - Uninstall all applications.
uninstallDebug - Uninstalls the Debug build.
uninstallDebugAndroidTest - Uninstalls the android (on device) tests for the Debug build.
uninstallRelease - Uninstalls the Release build.

Verification tasks
------------------
check - Runs all checks.
connectedAndroidTest - Installs and runs instrumentation tests for all flavors on connected devices.
connectedCheck - Runs all device checks on currently connected devices.
connectedDebugAndroidTest - Installs and runs the tests for debug on connected devices.
deviceAndroidTest - Installs and runs instrumentation tests using all Device Providers.
deviceCheck - Runs all device checks using Device Providers and Test Servers.
lint - Runs lint on all variants.
lintDebug - Runs lint on the Debug build.
lintRelease - Runs lint on the Release build.
lintVitalRelease - Runs lint on just the fatal issues in the release build.
test - Run unit tests for all variants.
testDebugUnitTest - Run unit tests for the debug build.
testReleaseUnitTest - Run unit tests for the release build.

To see all tasks and more detail, run gradlew tasks --all

複製代碼

能夠看到,這裏有不少的task.好比咱們在命令行執行gradlew clean就是clean.執行gradlew installDebug就是構建debug項目而後安裝到手機上.

4.2 編寫task

書寫task很是簡單,好比咱們在根目錄的build.gradle中加入一個hello的task

task hello() {
    println "hello world"

    //將給定的閉包 添加到此task操做鏈表的開頭
    doFirst {
        println "hello task doFirst"
    }

    doLast {
        println "hello task doLast"
    }
}
複製代碼

而後在命令行執行gradlew hello,輸出以下

setting 開始配置
setting 配置完成

> Configure project :
根build.gradle 開始配置
hello world
根build.gradle 配置完成

> Configure project :app
app build.gradle 開始配置
app build.gradle 配置完成

> Task :hello
hello task doFirst
hello task doLast
複製代碼

它會先配置完成,纔會執行.在一個task內部其實擁有一個action列表,執行的時候其實就是執行這個列表,它的類型是一個List.上面的doFirst和doLast就是建立action的兩個方法,文檔.doFirst是在最開始執行,doLast是在最後執行,大括號裏面傳入的是閉包.

4.3 task執行順序

task是有執行順序的,在建立完Android項目以後,根目錄下的build.gradle中,有一個clean的task.這個是AS自動給咱們生成的.

task clean(type: Delete) {
    delete rootProject.buildDir
}
複製代碼

咱們先在根目錄下建立test.txt文件,而後咱們在這個task中作一些改動,執行到clean這個task時刪除根目錄下的test.txt文件.

task clean(type: Delete) {
    delete rootProject.buildDir

    doLast {
        def file = new File('test.txt')
        delete file
        println "清理"
    }
}
複製代碼

而後咱們在hello這個task的下面寫上

hello.dependsOn clean
複製代碼

這樣就表示hello這個task依賴clean這個task,當執行hello這個task時須要先執行clean. 咱們在命令行執行gradlew hello看看是否是這樣.我執行以後它的輸出是

> Task :clean
清理

> Task :hello
hello task doFirst
hello task doLast
複製代碼

先執行clean,再執行hello這個task.並且還看到test.txt文件被刪除(若是看到沒刪除,刷新一下看看)了,那麼說明確實是clean先執行.

這個順序有什麼用?實際上是頗有用的,好比執行安裝task的時候,確定會先執行編譯,打包這些步驟.

4.4 自帶 gradle task

當咱們在AS中建立Android項目的時候,默認會帶一些Android的一些gradle task,這些task都是gradle和Android Gradle Plugin給咱們建立好的,能夠直接用.

Qe1fy9.png

好比咱們上面使用到的gradlew clean是用來清理項目的.和編譯相關的task主要有:build和assemble,其中build依賴assemble,也就是說執行build以前會先執行assemble。在Android上,會根據buildType和productFlavor的不一樣自動建立多個assembleXxx任務,如assembleDebug,assembleRelease等,assemble會依賴全部的assembleXxx任務,也就是說執行assemble會先執行assembleDebug,assembleRelease等一系列的assemble任務。

若是想看Android Gradle Plugin源碼,能夠在app/build.gradle中的dependencies下面引入

compileOnly 'com.android.tools.build:gradle:3.5.2'
複製代碼

而後就能夠在項目的External Libraries中看到該jar的源碼,

QeUB5R.png

好比clean這個task是在com.android.build.gradle.tasks.CleanBuildCache.java裏面定義的

@TaskAction
public void clean() throws IOException {
    Preconditions.checkNotNull(buildCache, "buildCache must not be null");
    buildCache.delete();
}
複製代碼

經過查詢gradle官方文檔可知,@TaskAction的做用:Marks a method as the action to run when the task is executed. 將方法標記爲執行任務時要運行的動做.

5.Build script blocks

還有一個東西,就是幾乎每一個項目都須要用到的地方,可是我以前卻根本不知道它真正的名字.就是Build script blocks,打開項目的根目錄的build.gradle文件.

buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

複製代碼

每一個項目都須要配置這些東西,可是咱們真的知道他們的含義麼?

首先是buildscript,查詢文檔可知:

void buildscript​(Closure configureClosure)

Configures the build script classpath for this project.

The given closure is executed against this project's ScriptHandler. The ScriptHandler is passed to the closure as the closure's delegate.
複製代碼

爲該項目配置構建腳本類路徑.參數是Closure,閉包.這個閉包是委託給了ScriptHandler,又去看看ScriptHandler

dependencies​(Closure configureClosure)	 Configures the dependencies for the script.
repositories​(Closure configureClosure)   Configures the repositories for the script dependencies.
複製代碼

dependencies​是添加編譯依賴項的,repositories​是爲腳本依賴項配置存儲庫.他們的配置,都是用閉包的形式.

而後dependencies​又是委託了DependencyHandler進行配置,對於怎麼配置,官方還給了示例

Example shows a basic way of declaring dependencies.

 apply plugin: 'java'
 //so that we can use 'implementation', 'testImplementation' for dependencies

 dependencies {
   //for dependencies found in artifact repositories you can use
   //the group:name:version notation
   implementation 'commons-lang:commons-lang:2.6'
   testImplementation 'org.mockito:mockito:1.9.0-rc1'

   //map-style notation:
   implementation group: 'com.google.code.guice', name: 'guice', version: '1.0'

   //declaring arbitrary files as dependencies
   implementation files('hibernate.jar', 'libs/spring.jar')

   //putting all jars from 'libs' onto compile classpath
   implementation fileTree('libs')
 }
複製代碼

6. 總結

本文帶你們梳理了Gradle的執行順序,Task和Build script blocks這些知識點.爲了更好的認識Gradle.如今對Gradle瞭解又深了一步,並且若是之後遇到不懂的還知道到哪裏去查文檔,方便快捷,不用再處處搜了.

相關文章
相關標籤/搜索