Gradle全解

我們Android項目里會有Java/Kotlin代碼,Xml文件,各種圖片音視頻資源文件等,那么Gradle 就是來幫我們打包生成 apk 的一個程序。

Gradle中,每一個待編譯的工程都叫一個Project。每一個Project在構建的時候都包含一系列的Task。比如一個Android APK的編譯可能包含:Java源碼編譯Task、資源編譯Task、JNI編譯Task、lint檢查Task、打包生成APK的Task、簽名Task等。一個Project到底包含多少個Task,其實是由編譯腳本指定的插件決定。插件是什么呢?插件就是用來定義Task,并具體執(zhí)行這些Task的東西。

Gradle與前身構建工具Maven

Gradle拋棄了Maven的基于XML的繁瑣配置,眾所周知XML的閱讀體驗比較差,對于機器來說雖然容易識別,但畢竟是由人去維護的。取而代之的是Gradle采用了領域特定語言Groovy的配置,大大簡化了構建代碼的行數。

Gradle 是個程序、Groovy 是特定領域 DSL 語言

Gradle 是運行在 JVM 實例上的一個程序,內部使用 Groovy 語言
Groovy 是一種 JVM 上的腳本語言,基于 java 擴展的動態(tài)語言

gradle的生命周期

  1. initalization初始化階段: 解析整個工程中所有Project,構建所有的Project對應的project對象,這個階段主要就是解析setting.gradle文件
  2. Configuration配置階段:解析所有的projects對象中的task,構建好所有的task拓撲圖,主要解析各個project下的build.gradle文件
  3. Execution執(zhí)行階段:執(zhí)行具體的的task及其依賴task

在項目的build.gradle中監(jiān)聽gradle的生命周期回調:

beforeEvaluate {
    println '配置階段開始前的監(jiān)聽回調'
}

afterEvaluate {
    println '配置階段完成以后的回調'
}

gradle.buildStarted {
    println 'build開始的回調監(jiān)聽'
}

gradle.buildFinished {
    println 'build完畢后的回調監(jiān)聽'
}

gradle.beforeProject {
    println 'gradle執(zhí)行前的回調監(jiān)聽'
}

gradle.afterProject {
    println 'gradle執(zhí)行前的回調監(jiān)聽'
}
gradle方法:
/**
 * 獲取所有Project
 */
getAllprojects().eachWithIndex { Project entry, int i ->
}

/**
 * 獲取所有子Project
 */
getSubprojects().eachWithIndex { Project entry, int i ->
}

/**
 * 配置subproject的所有project(module)
 */
subprojects {

}

/**
 * 獲取根Project
 */
getRootProject()
gradle.properties聲明,可在gradle中引用該配置
#dev          開發(fā)環(huán)境
#beta         測試環(huán)境
#release      正式上線環(huán)境
NET_TYPE=dev
android.useAndroidX=true
android.enableJetifier=true
android.injected.testOnly=false
kotlin.code.style=official
  • gradle倉庫

在項目的根build.gradle文件中,配置需要從哪里的倉庫下載jar包

repositories {
        //構建項目時會拉取gradle資源,而goole和jcenter在國內的網絡環(huán)境并不好,容易出現包拉取失敗的問題,那么就可以使用國內阿里的鏡像。
        //repositories里倉庫具有從上到下先后獲取順序
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
        maven{ url 'http://maven.aliyun.com/nexus/content/repositories/jcenter'}
        google()
        jcenter()
}
Gradle文件配置層級:
  • 一個工程包含一個setting.gradle文件和一個build.gradle文件。可能有多個Module,每個Module有自己的一個build.gradle。
  • setting.gradle: setting文件定義哪些module需要加入到編譯過程
  • 工程的build.gradle:該build文件最終會被應用到所有Module中
  • Gradle Wrapper: 對Gradle一層包裝,便于使用統(tǒng)一Gradle構建

gradle-wrapper.jar:具體業(yè)務邏輯實現的jar包
gradle-wrapper.properties:配置文件,包含篇配置信息如下圖:


gradle文件配置示例:

apply plugin: 'com.android.application'

android {

    signingConfigs {
        config {
            keyAlias ''
            keyPassword ''
            storeFile file('keystore.jks')
            storePassword ''
        }
    }

    compileSdkVersion 27
    defaultConfig {
        applicationId ""
        minSdkVersion 21
        targetSdkVersion 27
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        flavorDimensions "versionCode"

        renderscriptTargetApi 19
        renderscriptSupportModeEnabled true

        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11 -frtti -fexceptions"
            }
        }

        ndk {
            abiFilters 'armeabi-v7a'
        }

        lintOptions {
            abortOnError false
        }
    }

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }

    buildTypes {
        release {
            minifyEnabled true   
            shrinkResources true   
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            signingConfig signingConfigs.config
        }
        debug {
            minifyEnabled false
            signingConfig signingConfigs.config
        }
    }

    flavorDimensions "tier" 
    productFlavors {
        yingyongbao { dimension "tier" }
    }

    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
    }
}

android.lintOptions {   //忽略中英文大小寫
    checkReleaseBuilds false
    abortOnError false
}

allprojects {
    repositories {
        mavenCentral()
    }
}

repositories {
    flatDir {
        dir 'libs'

    }
}

dependencies {
    implementation 'com.android.support:appcompat-v7:27.1.1'
    implementation 'com.android.support:design:27.1.1'
    implementation 'com.jakewharton:butterknife:7.0.1'
}

配置說明:

apply plugin:

表明應用的插件的類型,工程項目是com.android.application類型,而Module則是com.android.library

android

這是編譯文件中最大的代碼塊,關于android 的所有特殊配置都在這里

defaultConfig

程序的默認配置

externalNativeBuild

native編譯支持
常用屬性
1.cmake:CMake工具編譯選項。
2.ndkBuild:ndk-build選項。

buildTypes

分為release版本和debug版本
常用屬性:

minifyEnabled 是否開啟混淆
shrinkResources 是否去除無用資源
signingConfigs 簽名配置信息
name:build type的名字
proguardFiles:混淆文件

lintOptions

Lint工具可選項參數
常用屬性
abortOnError false如果發(fā)現錯誤,lint工具是否應該退出這個程序。true表示退出。

productFlavors

項目打包變體配置

flavorDimensions "tier" 
productFlavors {
        yingyongbao { dimension "tier" }
    }
    productFlavors.all { flavor ->
        flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name]
    }
signingConfig

簽名配置信息

signingConfigs {
        config {
            keyAlias ''
            keyPassword ''
            storeFile file('keystore.jks')
            storePassword ''
        }
    }

keyAlias 簽名key的別名
keyPassword 簽名key的密碼
storeFile file 簽名key的路徑
storePassword store簽名密碼
v1SigningEnabled:是否使用jar簽名(又名v1簽名)
v2SigningEnabled:是否使用apk簽名(又名v2簽名)

repositories

代碼倉庫:Gradle支持從maven中央倉庫和JCenter上獲取構件

dependencies

dependencies屬于gradle 的依賴配置。它定義了當前項目需要依賴的其他庫。
我們在引用庫的時候,每個庫名稱包含三個元素:發(fā)布者標識:庫名:版本號
例如:

implementation 'com.alibaba:fastjson:1.2.8'

如果為implementation 'com.alibaba:fastjson:1.2.+'表示會使用庫的最新版本。但是每次編譯都要去做網絡請求查看是否有新版本導致編譯減慢。

gradle.properties配置
  • 加大可用編譯內存:
    org.gradle.jvmargs=-Xmx1024m

  • 開啟編譯守護進程
    org.gradle.daemon=true

  • 開啟并行編譯
    org.gradle.parallel=true

Gradle Plugin

Gradle是一個框架,作為框架,它負責定義流程和規(guī)則。而具體的編譯工作則是通過插件的方式來完成的。比如編譯Java有Java插件,編譯Groovy有Groovy插件,編譯Android APP有Android APP插件,編譯Android Library有Android Library插件。

  • 自定義task
task taskName {
    //do some things
 }

gradle中創(chuàng)建task的兩種方式

task myTask {
    println '執(zhí)行myTask'
}

tasks.create(name: 'myTask') {
    println '執(zhí)行myTask'
}

定義簡單task

//定義 task , 名字 hello
task hello {
    println "hello world"
}

//定義 task,名字 hello
task(hello2) {
    println "hello world2"
}

//定義 task,名字 hello3
task ('hello3') {
    println "hello world3"
}

task 本質上又是由一組被順序執(zhí)行的 Action 對象構成,Action其實是一段代碼塊,類似于Java中的方法。

task actionUse {
    //在Action 隊列頭部添加Action
    doFirst {

    }
    //在Action 隊列尾部添加Action
    doLast {

    }
    //創(chuàng)建一個 Action , 添加到 Action 列表的頭部
    doFirst(new Action<Task>() {
        @Override
        void execute(Task task) {

        }
    })
}
參考

https://mp.weixin.qq.com/s/UlnHuM2-Dqad3MXE77xJyg

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,848評論 25 709
  • 用兩張圖告訴你,為什么你的 App 會卡頓? - Android - 掘金 Cover 有什么料? 從這篇文章中你...
    hw1212閱讀 13,934評論 2 59
  • 說明 本文主要介紹和Gradle關系密切、相對不容易理解的配置,偏重概念介紹。部分內容是Android特有的(例如...
    搬磚的小明閱讀 16,145評論 1 62
  • 在 Android Studio 構建的項目中,基于 Gradle 進行項目的構建,同時使用 Android DS...
    Ant_way閱讀 7,584評論 0 16
  • 3. By落花水留痕 “老師?” 在一片黑暗中默默垂淚的柏木,被一聲怯怯的呼喚嚇的怔住了。她不想讓人看見自己現在的...
    紅白的書籤閱讀 466評論 0 1

友情鏈接更多精彩內容