Gradle入門系列(三)——初識Gradle與Project

初識Gradle

1、Gradle的基本概念

一個開源的項目自動化構建工具,創建在Apache Ant和Apache Maven概念的基礎上,並引入了基於Groovy的特定領域語言(DSL),而再也不使用XML形式管理構建腳本。同時,gradle仍是一個編程框架,可讓開發者使用編程的思想來實現應用構建。gradle的組成:android

  1. groovy核心語法
  2. build script block
  3. gradle api

2、Gradle的執行流程

生命週期 做用
Initialzation初始化階段 解析整個工程中全部project(讀取setting.gradle文件),構建全部的project對應的Project對象
Configuration配置階段 解析全部的project對象中的task,構建好全部task的拓撲圖
Execution執行階段 執行具體的task及其依賴的task

生命週期監聽:編程

// 配置階段開始前的監聽回調(即:在Initialzation與Configuration之間)
this.beforeEvaluate {}
// 配置階段完成後的監聽回調(即:在Configuration與Execution之間)
this.afterEvaluate {}
// gradle執行完畢後的回調監聽(即:在Execution以後)
this.gradle.buildFinished {}

// 與 this.beforeEvaluate {} 同樣
this.gradle.beforeProject {}
// 與 this.afterEvaluate {} 同樣
this.gradle.afterProject {}
複製代碼

Gradle中的Project

1、Idea與Gradle 對於project概念的區別

在Idea中,一個項目就是Project,一個Project下能夠包含多個模塊(Module),一個Module下,又能夠有多個Module,其樹狀結構以下:api

雖然能夠在Module中繼續建立子Module,但通常狀況下,咱們不會這麼作,最多就兩層。bash

+Project
--+Module
----+Module
----+Module
--+Module
--+Module
複製代碼

而對於Gradle而言,Idea中的不管是Project仍是Module,都是project,故樹狀結構以下:閉包

每一個project下,都必定會有一個build.gradleapp

+project        // rootProject
--+project      // subProject
----+project
----+project
--+project
--+project
複製代碼

2、project相關api

api 做用
getAllprojects() 獲取工程中全部的project(包括根project與子project)
getSubProjects() 獲取當前project下,全部的子project(在不一樣的project下調用,結果會不同,可能返回null)
getParent() 獲取當前project的父project(若在rooProject的build.gradle調用,則返回null)
getRootProject() 獲取項目的根project(必定不會爲null)
project(String path, Closure configureClosure) 根據path找到project,經過閉包進行配置(閉包的參數是path對應的Project對象)
allprojects(Closure configureClosure) 配置當前project和其子project的全部project
subprojects(Closure configureClosure) 配置子project的全部project(不包含當前project)
// rootProject build.gradle下配置:
// 一、Project project(String path, Closure configureClosure);
project('app') { Project project ->       // 一個參數時,能夠省略不寫,這裏只是爲了明確參數的類型
  apply plugin : 'com.android.application'
  group 'com.lqr'
  version '1.0.0-release'
  dependencies {}
  android {}
}

// 二、allprojects(Closure configureClosure)
allprojects {
  group 'com.lqr'
  version '1.0.0-release'
}

// 三、subprojects(Closure configureClosure)
subprojects { Project project -> 
  if(project.plugins.hasPlugin('com.android.library')){
    apply from: '../publishToMaven.gradle'
  }
}
複製代碼

3、屬性相關api

一、在gradle腳本文件中使用ext塊擴展屬性

父project中經過ext塊定義的屬性,子project能夠直接訪問使用框架

// rootProject : build.gradle
// 定義擴展屬性
ext {
  compileSdkVersion = 25
  libAndroidDesign = 'com.android.support:design:25.0.0'
}

// app : build.gradle
android {
  compileSdkVersion = this.compileSdkVersion // 父project中的屬性,子project能夠直接訪問使用
  ...
}
dependencies {
  compile this.libAndroidDesign // 也可使用:this.rootproject.libAndroidDesign
  ...
}

複製代碼

二、在gradle.properties文件中擴展屬性

hasProperty('xxx'):判斷是否有在gradle.properties文件定義xxx屬性。 在gradle.properties中定義的屬性,能夠直接訪問,但獲得的類型爲Object,通常須要經過toXXX()方法轉型。maven

// gradle.properties
// 定義擴展屬性
isLoadTest=true
mCompileSdkVersion=25

// setting.gradle
// 判斷是否須要引入Test這個Module
if(hasProperty('isLoadTest') ? isLoadTest.toBoolean() : false) {
  include ':Test'
}

// app : build.gradle
android {
  compileSdkVersion = mCompileSdkVersion.toInteger()
  ...
}
複製代碼

4、文件相關api

api 做用
getRootDir() 獲取rootProject目錄
getBuildDir() 獲取當前project的build目錄(每一個project都有本身的build目錄)
getProjectDir() 獲取當前project目錄
File file(Object path) 定位一個文件,相對於當前project開始查找
ConfigurableFileCollection files(Object... paths) 定位多個文件,與file相似
copy(Closure closure) 拷貝文件
fileTree(Object baseDir, Closure configureClosure) 定位一個文件樹(目錄+文件),可對文件樹進行遍歷
// 打印common.gradle文件內容
println getContent('common.gradle')
def getContent(String path){
  try{
    def file = file(path)
    return file.text
  }catch(GradleException e){
    println 'file not found..'
  }
  return null
}

// 拷貝文件、文件夾
copy {
  from file('build/outputs/apk/')
  into getRootProject().getBuildDir().path + '/apk/'
  exclude {} // 排除文件
  rename {} // 文件重命名
}

// 對文件樹進行遍歷並拷貝
fileTree('build/outputs/apk/') { FileTree fileTree ->
    fileTree.visit { FileTreeElement element ->
        println 'the file name is: '+element.file.name
        copy {
            from element.file
            into getRootProject().getBuildDir().path + '/test/'
        }
    }
}
複製代碼

5、依賴相關api

配置工程倉庫及gradle插件依賴ide

// rootProject : build.gradle
buildscript { ScriptHandler scriptHandler ->
    // 配置工程倉庫地址
    scriptHandler.repositories { RepositoryHandler repositoryHandler ->
        repositoryHandler.jcenter()
        repositoryHandler.mavenCentral()
        repositoryHandler.mavenLocal()
        repositoryHandler.ivy {}
        repositoryHandler.maven { MavenArtifactRepository mavenArtifactRepository ->
            mavenArtifactRepository.name 'personal'
            mavenArtifactRepository.url 'http://localhost:8081/nexus/repositories/'
            mavenArtifactRepository.credentials {
                username = 'admin'
                password = 'admin123'
            }
        }
    }
    // 配置工程的"插件"(編寫gradle腳本使用的第三方庫)依賴地址
    scriptHandler.dependencies {
        classpath 'com.android.tools.build:gradle:2.2.2'
        classpath 'com.tencent.tinker-patch-gradle-plugin:1.7.7'
    }
}

// ============ 上述腳本簡化後 ============

buildscript {
    // 配置工程倉庫地址
    repositories {
        jcenter()
        mavenCentral()
        mavenLocal()
        ivy {}
        maven {
            name 'personal'
            url 'http://localhost:8081/nexus/repositories/'
            credentials {
                username = 'admin'
                password = 'admin123'
            }
        }
    }
    // 配置工程的"插件"(編寫gradle腳本使用的第三方庫)依賴地址
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.2'
        classpath 'com.tencent.tinker-patch-gradle-plugin:1.7.7'
    }
}
複製代碼

配置應用程序第三方庫依賴工具

compile: 編譯依賴包並將依賴包中的類打包進apk。 provided: 只提供編譯支持,但打包時依賴包中的類不會寫入apk。

// app : build.gradle
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar']) // 依賴文件樹
    // compile file() // 依賴單個文件
    // compile files() // 依賴多個文件
    compile 'com.android.support:appcompat-v7:26.1.0' // 依賴倉庫中的第三方庫(即:遠程庫)
    compile project('mySDK') { // 依賴工程下其餘Module(即:源碼庫工程)
      exclude module: 'support-v4' // 排除依賴:排除指定module
      exclude group: 'com.android.support' // 排除依賴:排除指定group下全部的module
      transitive false // 禁止傳遞依賴,默認值爲false
    }
  
    // 棧內編譯
    provided('com.tencent.tinker:tinker-android-anno:1.9.1')
}
複製代碼

provided的使用場景:

  1. 依賴包只在編譯期起做用。(如:tinker的tinker-android-anno只用於在編譯期生成Application,並不須要把該庫中類打包進apk,這樣能夠減少apk包體積)
  2. 被依賴的工程中已經有了相同版本的第三方庫,爲了不重複引用,可使用provided。

6、外部命令api

// copyApk任務:用於將app工程生成出來apk目錄及文件拷貝到本機下載目錄
task('copyApk') {
    doLast {
        // gradle的執行階段去執行
        def sourcePath = this.buildDir.path + '/outputs/apk'
        def destinationPath = '/Users/lqr/Downloads'
        def command = "mv -f ${sourcePath} ${destinationPath}"
        // exec塊代碼基本是固定的
        exec {
            try {
                executable 'bash'
                args '-c', command
                println 'the command is executed success.'
            }catch (GradleException e){
                println 'the command is executed failed.'
            }
        }
    }
}
複製代碼
相關文章
相關標籤/搜索