Gradle在Android下的詳解及最佳實(shí)踐

  • 閱讀本文需要10min+
    關(guān)鍵字
    Gradle、groovy

目錄

  • 前言
  • 簡(jiǎn)介
  • groovy
    1. 簡(jiǎn)介
    2. 數(shù)據(jù)語(yǔ)法
    3. 數(shù)據(jù)類型
  • gradle
    1. 簡(jiǎn)介
    2. 依賴管理
    3. 幾個(gè)常用Task
    4. 新版本gradle屬性介紹( android plugin 3.0.0搭配Gradle 3.4版本以上)
  • 最佳實(shí)踐
    1. 實(shí)踐一
    2. 實(shí)踐二
  • 參考

前言

Gradle的知識(shí)體系非常龐大,市面上有專門(mén)講解的書(shū)籍,如果想全面了解可以購(gòu)買(mǎi)書(shū)籍或者查看網(wǎng)上的系列教程。本文只帶你入門(mén)以及熟悉在Android下常見(jiàn)的使用場(chǎng)景。

簡(jiǎn)介

gradle還是glide?作為一個(gè)Android開(kāi)發(fā)者,有時(shí)候會(huì)把兩者給拼寫(xiě)錯(cuò)誤,前者也就是本文的主角,是一個(gè)自動(dòng)化構(gòu)建(build)的工具,說(shuō)到構(gòu)建,有的同學(xué)可能不太理解,初略的理解就是根據(jù)輸入的信息執(zhí)行一些操作,然后得到目標(biāo)產(chǎn)物的過(guò)程稱為構(gòu)建。構(gòu)建不同于編譯工具,它用于組織編譯,單元測(cè)試,發(fā)布等操作。這里提到構(gòu)建,就順便提一下構(gòu)建工具的發(fā)展史

  1. Makefile
    這是什么鬼,我也不熟,不過(guò)據(jù)說(shuō)是最元老的構(gòu)建工具,至今仍然是Linux上C/C++開(kāi)發(fā)最流行的構(gòu)建工具,上了G界別的Android系統(tǒng)的開(kāi)源項(xiàng)目就是由Makefile構(gòu)建
  2. Ant
    Java出世,是為跨平臺(tái)而生,而Makefile成了一個(gè)大大的絆腳石,Java開(kāi)發(fā)人員急切的需要一個(gè)跨平臺(tái)的構(gòu)建工具,最好能在JVM上運(yùn)行,于是Ant誕生了,Ant使用的xml文件格式
  3. Maven
    Ant出現(xiàn),為很多Java開(kāi)發(fā)者帶來(lái)了福音,不過(guò)伴隨著軟件行業(yè)的日益發(fā)展,規(guī)模變大,大家發(fā)現(xiàn)Ant不夠用,于是Maven出世,Maven他使用XML文件格式(pom.xml)
  4. Gradle
    2004年,Maven發(fā)布后,非常受Java開(kāi)發(fā)人員愛(ài)戴,然而,軟件史上,再偉大的項(xiàng)目都有他喪失光芒的一天,于是gradle出世了,在他問(wèn)世之后,Google迅速把Android的編譯環(huán)境遷移到gradle,當(dāng)你搜索gradle時(shí),你應(yīng)該會(huì)有這樣的感覺(jué),為何人們都如此愛(ài)好這個(gè)工具,其中很大一部分原因是gradle使用了基于Groovy的DSL語(yǔ)言作為構(gòu)建腳本語(yǔ)言的而不是以往的XML。

PS: 有關(guān)構(gòu)建工具的發(fā)展的詳細(xì)歷史,可以參考[這篇文章](http://blog.csdn.net/yanquan345/
article/details/46710869)

groovy

簡(jiǎn)介

Groovy是一種動(dòng)態(tài)語(yǔ)言,和Java一樣,運(yùn)行在Java虛擬機(jī)中,簡(jiǎn)單粗暴的理解,可以認(rèn)為Groovy擴(kuò)展了Java語(yǔ)言,除了語(yǔ)言和Java相通外,Groovy有時(shí)候又像一種腳本語(yǔ)言。當(dāng)我執(zhí)行 Groovy 腳本時(shí),Groovy 會(huì)先將其編譯成 Java 類字節(jié)碼,然后通過(guò) Jvm 來(lái)執(zhí)行這個(gè) Java 類,實(shí)際上,由于 Groovy Code 在真正執(zhí)行的時(shí)候已經(jīng)變成了 Java 字節(jié)碼,所以 JVM 根本不知道自己運(yùn)行的是 Groovy 代碼。

使用Groovy 還可以開(kāi)發(fā)Android應(yīng)用,可以參考[這篇文章](http://www.itdecent.cn/p/
399ae2d0f313)

數(shù)據(jù)語(yǔ)法

既然Groovy是一種語(yǔ)言,它必然有他的語(yǔ)言編寫(xiě)規(guī)則,下面只粗略的介紹,更多細(xì)節(jié)可以查看官方文檔

  1. Groovy 注釋標(biāo)記和 Java 一樣,支持//或者/**/
  2. Groovy 語(yǔ)句可以不用分號(hào)結(jié)尾。
  3. Groovy 中支持動(dòng)態(tài)類型,即定義變量的時(shí)候可以不指定其類型。Groovy 中,變量定義可以使用關(guān)鍵字 def。注意,雖然 def 不是必須的,但是為了代碼清晰,建議還是使用 def 關(guān)鍵字
def variable1 = 1   //可以不使用分號(hào)結(jié)尾  
def varable2 = "I am a person"
def  int x = 1   //變量定義時(shí),也可以直接指定類型  
  1. 函數(shù)定義時(shí),參數(shù)的類型也可以不指定。
String testFunction(arg1,arg2){//無(wú)需指定參數(shù)類型  
  ...
}

數(shù)據(jù)類型

  1. 一個(gè)是 Java 中的基本數(shù)據(jù)類型。
  2. 另外一個(gè)是 Groovy 中的容器類。
  3. 最后一個(gè)非常重要的是閉包。

這一塊的知識(shí)點(diǎn)詳細(xì)可以查看[這個(gè)地址](http://wiki.jikexueyuan.com/project/deep-android- gradle/three-three.html),如果你想詳細(xì)了解Groovy這門(mén)語(yǔ)言,可以查看IBM的中文教程,更多細(xì)節(jié)可以查看官方文檔

gradle

簡(jiǎn)介

Gradle是一個(gè)框架,它定義了一套自己的規(guī)則。Gradle 中,每一個(gè)待編譯的工程都叫一個(gè) Project。我們點(diǎn)擊build.gradle會(huì)跳轉(zhuǎn)到gradle源碼Project.java類中,每一個(gè) Project 在構(gòu)建的時(shí)候都包含一系列的 Task。比如一個(gè) Android APK 的編譯可能包含:Java 源碼編譯 Task、資源編譯 Task、JNI 編譯 Task、lint 檢查 Task、打包生成 APK 的 Task、簽名 Task 等(在后面我們會(huì)專門(mén)介紹幾個(gè)常用Task)。
Android Studio幾個(gè)有關(guān)gradle的配置文件,如下圖


gradle配置圖

更多細(xì)節(jié)可以查看這里,或者查看官方文檔

依賴管理

首先我們看下面一段gradle代碼

  apply plugin: 'com.android.application'
  repositories {
          jcenter()
      }
  dependencies {
      compile 'com.android.support:appcompat-v7:26.+‘
      testCompile 'junit:junit:4.12'
}

這段腳本是什么意思呢?首先com.android.support:appcompat-v7:26.+(倉(cāng)庫(kù)中26版本下的最新版,不過(guò)官方不建議這么寫(xiě))這貨是編譯期必須依賴,并且它相關(guān)的依賴也會(huì)一起加載進(jìn)來(lái)(v4包),該腳本同時(shí)還申明項(xiàng)目測(cè)試階段需要4.12版本的junit。同時(shí)告訴gradle可以去jcenter倉(cāng)庫(kù)去加載這些依賴,下面將較詳細(xì)的描述。

依賴配置

  1. 按依賴的作用分為以下幾部分
    • compile
      編譯范圍依賴在所有的classpath范圍可用,同時(shí)它們也會(huì)被打包到apk中
    • apk
      apk的意思是apk中存在,但是不會(huì)加入編譯中(用的比較少)
    • provided
      提供編譯支持,但是不會(huì)寫(xiě)入apk
    • runtime
      runtime依賴在運(yùn)行和測(cè)試系統(tǒng)的時(shí)候需要,編譯的時(shí)候不需要
    • testCompile&androidTestCompile
      測(cè)試編譯需要附加的依賴

PS: 在gradle3.4版本,以上配置關(guān)鍵字被調(diào)整優(yōu)化了,下面會(huì)講解到。
測(cè)試運(yùn)行期需要的依賴

  1. 按依賴的加入方式分為兩種
    (1) 遠(yuǎn)程依賴
    遠(yuǎn)程依賴指的是library被放置到遠(yuǎn)程(可以是自己的maven庫(kù)或者是maven中心庫(kù)或jcenter),需要的時(shí)候在maven方法加入url地址
repositories {
       maven {
           url "http://repo.acmecorp.com/maven2"
       }
}

(2) 本地依賴

  • 文件依賴
dependencies {
       compile fileTree(dir: 'libs', include: ['*.jar'])
}

默認(rèn)新建Android項(xiàng)目會(huì)自動(dòng)生成這端代碼,這段代碼的意思是把libs文件夾下的所有jar文件添加到編譯路徑以及最后的apk文件(如果你想添加單個(gè)文件可以compile files('libs/okhttp.jar')

  • arr依賴
    首先得先把a(bǔ)rr文件拷貝到自己創(chuàng)建的一個(gè)文件夾(比如arrs),然后把a(bǔ)rr文件拷貝到該文件夾里,然后添加該文件夾作為依賴庫(kù)
repositories {
    flatDir {
        dirs 'aars' 
    }
}

最后把該文件夾下的arr作為依賴

dependencies {
       compile(name:'libraryname', ext:'aar')
}

這個(gè)會(huì)告訴gradle,在aars文件夾下,添加一個(gè)叫做libraryname的文件,且其后綴是aar的作為依賴。

  • 工程依賴
    如果把其他工程作為模塊,需要在setting.gradle文件添加
include ':app', ':library'

然后在module使用該依賴

 dependencies {
       compile project(':library')
  }
  • narive包(so包)
    使用c/c++編寫(xiě)的library會(huì)叫做so包,Android插件默認(rèn)支持native包,把.so文件放入對(duì)應(yīng)的文件夾中:
app
   ├── AndroidManifest.xml
   └── jniLibs
       ├── armeabi
       │   └── nativelib.so
       ├── armeabi-v7a
       │   └── nativelib.so
       ├── mips
       │   └── nativelib.so
       └── x86
           └── nativelib.so

幾個(gè)常用Task

在Android Studio 的Terminal輸入"./gradlew tasks --all",數(shù)據(jù)一大串task,如下(圖片太大,我把其分為三部分)

圖1

圖2

圖3

這里列出里Project ArchitectureSample支持的Task(Task 也可以自定義),這里簡(jiǎn)介一下我常用的一些Task,更多命令可以查看gradle官方文檔

./gradlew -v //查看構(gòu)建版本
./gradlew assembleDebug  //編譯并打Debug包
./gradlew assembleRelease // 編譯并打Release的包
./gradlew installRelease  //  Release模式打包并安裝
./gradlew uninstallRelease //卸載Release模式包
./gradlew -q app:dependencies //查看app module下的依賴
./gradlew install[productFlavorsName] app:assembleDebug//結(jié)合productFlavors多渠道打包

注意:在window下可以直接運(yùn)行 gradlew 如果是Linux 或者 mac 命令為 gradle gradlew 這里都簡(jiǎn)寫(xiě)成 ./gradle

新版本gradle屬性介紹( android plugin 3.0.0搭配Gradle 3.4版本以上)

  • Implementation vs compile
    升級(jí)到新版本的gradle,發(fā)現(xiàn)Android Studio 新建工程發(fā)現(xiàn)默認(rèn)添加的依賴改成了Implementation,而不是之前的compile,同樣替換的有 api 替換compile compileOnly 替換provided ,runtimeOnly替換apk,Implementation較compile有什么改進(jìn)呢,簡(jiǎn)單一句話就是加快了編譯速度,稍微復(fù)雜的一句話就是Implementation較compile改動(dòng)底層library不需要重新編譯整個(gè)Project,更細(xì)節(jié)可以看這篇文章,更多新特性可以查看相應(yīng)官方文檔

ps:如果沒(méi)有升級(jí)的建議盡快升級(jí),為了更好的體驗(yàn),下面的截圖取自官方文檔是不同版本編譯速度的比較
gradle不同版本速度比較

最佳實(shí)踐

實(shí)踐一

在module的build.gradle

android {
    compileSdkVersion project.COMPILE_SDK as int
    buildToolsVersion project.BUILD_TOOLS_VERSION

    defaultConfig {
        minSdkVersion project.MIN_SDK as int
        targetSdkVersion project.TARGET_SDK as int
        .....
        }
        ......
      }
      
      dependencies {
       compile "com.android.support:appcompat-v7:${SUPPORT_LIBRARY}"
       compile "com.squareup.retrofit2:retrofit:${retrofit}"
       compile "com.squareup.retrofit2:converter-gson:${retrofit}"
       compile "com.squareup.retrofit2:converter-scalars:${retrofit}"
       compile "com.squareup.okhttp3:okhttp:${OKHTTP}"
       compile "com.squareup.okhttp3:logging-interceptor:${OKHTTP}"
    ......
    }

在gradle.properties直接定義

COMPILE_SDK=25
MIN_SDK=16
TARGET_SDK=25
BUILD_TOOLS_VERSION=25.0.3
SUPPORT_LIBRARY=25.0.1
OKHTTP=3.6.0
retrofit = 2.2.0

實(shí)踐二

在project根目錄新建versions.gradle

ext {

    android = [
               compileSdkVersion       : 25,
               buildToolsVersion       : "25.0.3",
               minSdkVersion           : 15,
               targetSdkVersion        : 25,
               versionCode             : 130,
               versionName             : "2.1.5"
    ]

     version = [
                   androidSupportSdkVersion: "25.4.0",
                   retrofitSdkVersion      : "2.3.0",
                   glideSdkVersion         : "4.0.0",
                   butterknifeSdkVersion   : "8.7.0",
                   rxlifecycleSdkVersion   : "1.0",
                   rxlifecycle2SdkVersion  : "2.1.0",
                   espressoSdkVersion      : "2.2.2"
        ]
        
         dependencies = [
                //support
                "appcompat-v7"             : "com.android.support:appcompat-v7:${version["androidSupportSdkVersion"]}",
                "design"                   : "com.android.support:design:${version["androidSupportSdkVersion"]}",
                "support-v4"               : "com.android.support:support-v4:${version["androidSupportSdkVersion"]}",
                "cardview-v7"              : "com.android.support:cardview-v7:${version["androidSupportSdkVersion"]}",
                "annotations"              : "com.android.support:support-annotations:${version["androidSupportSdkVersion"]}",
                "recyclerview-v7"          : "com.android.support:recyclerview-v7:${version["androidSupportSdkVersion"]}",
                "glide"                    : "com.github.bumptech.glide:glide:${version["glideSdkVersion"]}",
                "retrofit"                 : "com.squareup.retrofit2:retrofit:${version["retrofitSdkVersion"]}",
                "gson"                     : "com.google.code.gson:gson:2.8.1"
   }

然后在project的build.gradle引入apply from: "config.gradle",moudle 的build.gradle的代碼如下

android {
    compileSdkVersion rootProject.ext.android["compileSdkVersion"]
    buildToolsVersion rootProject.ext.android["buildToolsVersion"]
    ......
     defaultConfig {
        applicationId "com.example.tml.gradle.demo"
        minSdkVersion rootProject.ext.android["minSdkVersion"]
        targetSdkVersion rootProject.ext.android["targetSdkVersion"]
        versionCode rootProject.ext.android["versionCode"]
        versionName rootProject.ext.android["versionName"]
        ......
    }
    }
    
    dependencies{

       compile(rootProject.ext.dependencies["appcompat-v7"]) {
            exclude module: 'support-annotations'
            exclude module: 'support-v4'
          }
      compile(rootProject.ext.dependencies["design"]) {
          exclude module: 'support-annotations'
          exclude module: 'appcompat-v7'
          exclude module: 'support-v4'
          }
      compile(rootProject.ext.dependencies["retrofit"]) {
          exclude module: 'okhttp'
          exclude module: 'okio'
          }
      compile(rootProject.ext.dependencies["retrofit"]) {
          exclude module: 'okhttp'
          exclude module: 'okio'
          }
      compile(rootProject.ext.dependencies["glide"]) {
          exclude module: 'support-v4'
      }
      compile rootProject.ext.dependencies["gson"]
        ......
    }

參考

http://wiki.jikexueyuan.com/project/deep-android-gradle/
http://avatarqing.github.io/Gradle-Plugin-User-Guide-Chinese-Verision/basic_project/README.html
https://docs.gradle.org/current/javadoc/
http://www.groovy-lang.org/api.html
https://developer.android.com/studio/releases/gradle-plugin.html
https://developer.android.com/studio/build/index.html?hl=zh-cn
https://juejin.im/entry/59476897da2f60006786029f
https://segmentfault.com/a/1190000004241503

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

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容