依賴管理是Gradle的一個亮點。在最好的情況下,你只需要在構(gòu)建文件中添加一行代碼,Gradle就可以從遠程倉庫下載依賴并確保可用。當你所需的依賴還有它自己的依賴時,Gradle會自動接管這些事情。依賴的依賴稱為傳遞依賴(transitive dependencies
)。
本章將介紹依賴管理的概念,并通過多種方式在Android工程中引入依賴。主要內(nèi)容有:
- 倉庫
- 本地依賴
- 依賴的幾個概念
倉庫
我們所說的依賴通常是指外部依賴,比如其他開發(fā)者提供的庫。手動管理依賴是非常困難的事情。你需要找到這個庫,然后下載JAR包,并拷貝到工程中,最后再引用它。一般這些JAR包的名稱中并不包含版本信息,所以你需要自己添加,以便日后升級。你還需要確保這些庫保存在一個源管理系統(tǒng)中,這樣其他團隊成員才可以直接引用基礎(chǔ)代碼,而不需要手動去下載依賴。
使用倉庫可以解決這些問題。一個倉庫可以看做是一個文件集。Gradle默認不會為你的工程定義任何倉庫,所以你需要自己在repositories
塊中添加。如果你使用的是Android Studio,它會幫你做這些。我們在前面的章節(jié)簡單提到了repositories
塊,如下:
repositories {
jcenter()
}
Gradle支持三種不同的倉庫:Maven、Ivy和靜態(tài)文件或者目錄。在構(gòu)建的execution期間,Gradle會從倉庫中獲取這些依賴。Gradle同樣會保存一個本地的緩存,這樣同一個版本的依賴只會下載一次。
一個依賴由三個元素定義:
- group指明了創(chuàng)建這個倉庫的組織,通常是域名的翻轉(zhuǎn)。
- name是倉庫的唯一標識
- version指定倉庫的版本
基于這三個元素,一個依賴可以在dependencies
塊中這樣聲明:
dependencies {
compile 'com.google.code.gson:gson:2.3'
compile 'com.squareup.retrofit:retrofit:1.9.0'
}
這是Groovy中map的一種簡寫,全寫如下:
dependencies {
compile group: 'com.google.code.gson', name: 'gson', version:'2.3'
compile group: 'com.squareup.retrofit', name: 'retrofit', version: '1.9.0'
}
一個依賴的必需元素是name,group和version是可選的。盡管如此,我們?nèi)越ㄗh添加上group以使依賴變得清晰,添加上version,這樣可以確保依賴不會自動更新,否則會打斷構(gòu)建。
預(yù)置倉庫
為了方便,Gradle預(yù)置了三個Maven倉庫:JCenter,Maven Central和本地Maven倉庫。可以添加如下代碼來引入它們:
repositories {
mavenCentral()
jcenter()
mavenLocal()
}
Maven Central和JCenter是兩個廣泛使用的在線倉庫。你不必同時使用它們,我們推薦使用JCenter,這也是Android Studio創(chuàng)建的Android工程的默認倉庫。JCenter是Maven Central的父集,所以當你做開關(guān)的時候,你可原封不動的保留已定義的依賴項。在此之上,它還支持HTTPS,這和Maven Central不同。
本地Maven倉庫是一個你所使用的所有依賴的本地緩存,你也可以添加你自己的依賴。默認情況下,這個倉庫在home目錄的.m2
文件夾下。在Linux或者Mac OS X中,路徑為~/.m2
,Windows中為%UserProfile%\.m2
。
除了預(yù)置的倉庫,你也可以添加其他公有的或者私有的倉庫。
遠程倉庫
有些組織創(chuàng)建有趣的插件或者倉庫,并且傾向于將它們部署在自己的Maven或者Ivy服務(wù)器上。為了將它們添加到你的構(gòu)建中,你只需要在maven
塊中添加URL地址:
repositories {
maven {
url "http://repo.acmecorp.com/maven2"
}
}
這同樣適用于Ivy倉庫。Apache Ivy在Ant中是一個流行的依賴管理者。Gradle以與Maven庫相同的格式支持這些倉庫。
repositories {
ivy {
url "http://repo.acmecorp.com/repo"
}
}
如果你的組織有自己的倉庫,需要有證書才可以訪問,可以這樣寫:
repositories {
maven {
url "http://repo.acmecorp.com/maven2"
credentials {
username 'user'
password 'secretpassword'
}
}
}
Maven和Ivy使用同樣的方式。
保存證書
在構(gòu)建文件中保存證書不是一個好主意。構(gòu)建文件是純文本的,并被檢入源控制系統(tǒng)。更好的方式是使用單獨的Gradle properties文件來保存,就像我們在第二章看到的那樣。
本地倉庫
在你的硬盤或者網(wǎng)盤上運行Maven或者Ivy倉庫是可行的。為將其添加到你的構(gòu)建中,你只需要配置一個相對或者絕對的URL地址:
repositories {
maven {
url "../repo"
}
}
新建的Android工程,默認依賴Android Support Library。在使用SDK Manager安裝Google倉庫時,會在你的硬盤上創(chuàng)建兩個Maven倉庫:ANDROID_SDK/extras/google/m2repository 和 ANDROID_SDK/extras/android/m2repository。這是Gradle獲取Google提供的庫的地址,比如:Android Spport Library和Google Play Services。
你也可以使用flatDirs
添加一個常規(guī)目錄作為倉庫。它允許你在dependency
塊中從該目錄添加文件。
repositories {
flatDir {
dirs 'aars'
}
}
本章的后續(xù)內(nèi)容中,在講解庫工程時, 我們會看一個使用它的例子。
本地依賴
某種情況下,你可能仍需要手動下載Jar包或者native庫。或許你想創(chuàng)建你自己的倉庫,這樣就可以在多個工程中重復(fù)使用它,而且不必將他發(fā)布到公有或者私有的倉庫中。在這種情況下,不可能去使用任何在線的資源,你需要使用其他的方式來添加依賴。我們會講述如何使用文件依賴,如何包含native庫,以及如何在你的工程中引用庫工程。
文件依賴
你可以使用files
方法來添加一個Jar文件依賴
dependencies {
compile files('libs/domoarigato.jar')
}
文件過多時,你可以添加文件夾:
dependencies {
compile fileTree('libs')
}
默認情況下,新建的Android工程有一個libs目錄,并且被添加為依賴目錄。你還可以添加過濾器,只添加Jar包為依賴:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
}
這意味著在Android Studio創(chuàng)建的任何工程中,你可以在libs
文件夾下放置Jar包,它會被自動包含在編譯路徑和最終的APK中。
Native庫
用C或C++編寫的庫可以編譯成特定平臺的native代碼。這些庫由幾個.so
文件組成,每個文件對應(yīng)一個平臺。Android 插件默認支持native庫,你只需要在模塊中創(chuàng)建jniLibs
目錄,并且為每個平臺創(chuàng)建相應(yīng)的子目錄就可以了。最后把.so
文件放入對應(yīng)的子目錄。
結(jié)構(gòu)如下:
app
├── AndroidManifest.xml
└── jniLibs
├── armeabi
│ └── nativelib.so
├── armeabi-v7a
│ └── nativelib.so
├── mips
│ └── nativelib.so
└── x86
└── nativelib.so
如果這個規(guī)則對你不適用,你可以在構(gòu)建文件中自定義目錄:
android {
sourceSets.main {
jniLibs.srcDir 'src/main/libs'
}
}
庫工程
如果你想分享一個使用了Android API或者包含Android資源的庫,你需要創(chuàng)建一個庫工程。庫工程和應(yīng)用工程大體相同。你可以使用同樣的任務(wù)來構(gòu)建和測試庫工程,它們同樣可以有不同的構(gòu)建變體。不同的是輸出。應(yīng)用工程會生成一個APK,它可以安裝和運行在Android設(shè)備上;庫工程會生成一個.aar
文件,該文件可以作為Android應(yīng)用工程的庫。
創(chuàng)建和使用庫工程模塊
在構(gòu)建腳本中,使用Android庫插件來代替Android應(yīng)用插件:
apply plugin: 'com.android.library'
有兩種方式可以在你的應(yīng)用中包含一個庫工程。
- 將其作為模塊包含在工程中
- 創(chuàng)建一個
.aar
文件,該文件可以多個應(yīng)用中重復(fù)使用。
第一種方式需要將模塊添加到settings.gradle
文件中,并將其作為應(yīng)用模塊的依賴。settings文件如下:
include ':app', ':library'
在這種情況下,庫模塊被稱為library
,相應(yīng)的會有一個同名的文件夾。為了使用這個庫,需要在應(yīng)用模塊的build.gradle
文件將其添加為依賴:
dependencies {
compile project(':library')
}
這樣應(yīng)用模塊的類路徑將會包含庫的輸出。我們將在第五章詳細討論這個方法。
使用.arr文件
如果你想創(chuàng)建一個可以在不同Android應(yīng)用中重復(fù)使用的庫,你可以構(gòu)建一個.aar
文件,然后將其作為依賴添加到工程中。構(gòu)建庫時,.aar
文件會在模塊目錄的build/output/aar/
文件夾下生成。為了使用它,你需要在應(yīng)用模塊中創(chuàng)建一個文件夾,將.aar
文件拷貝其中,然后添加該目錄為倉庫。
repositories {
flatDir {
dirs 'aars'
}
}
這樣每個被放置其中的文件都會被依賴。你可以如下引用這些依賴:
dependencies {
compile(name:'libraryname', ext:'aar')
}
這樣Gradle就會添加libraryname.aar
作為依賴。
依賴的幾個概念
這里有一些依賴相關(guān)的概念,值得了解一下。其中一個是configurations
,它解釋了我們在本章用到的compile
關(guān)鍵字。
Configurations
有時我們需要使用一些特定設(shè)備提供的SDK,比如某些廠商的藍牙SDK。為了編譯代碼,你需要將SDK添加到compile classpath中。但你并不需要將其包含在APK中,因為它已經(jīng)存在于設(shè)備上了。這時候依賴的配置就起作用了。
Gradle將依賴分成各種配置,由文件集命名。下面是Android應(yīng)用或者庫的標準配置:
- compile
- apk
- provided
- testCompile
- androidTestCompile
compile
配置是默認的,包含編譯main應(yīng)用所需的全部依賴。該配置中的依賴不僅包含在類路徑中,還包含在生成的APK中。
apk
配置只會包含在APK中,不會包含在類路徑中。
provided
與apk
相反。這兩種配置只接受JAR依賴項,試圖將庫工程加入其中會導(dǎo)致錯誤。
testCompile
和androidTestCompile
會添加測試所需的特定外部庫。這兩個配置可以添加測試框架,比如JUnit或者Espresso。它們只在運行測試相關(guān)任務(wù)的時候才會用到。你只想在測試APK中使用這些框架,而不是發(fā)布的APK中。
除了這些標準的配置,Android插件還會為每個構(gòu)建變體創(chuàng)建配置,比如debugCompile,releaseProvided等。如果你只想在debug版本添加一個日志框架,這將會非常有用。你會在第四章學(xué)習(xí)到更多。
語義版本控制
版本控制是依賴管理很重要的一個方面。添加到倉庫(如JCenter)的依賴被認為遵循一組版本控制規(guī)則,稱為語義版本控制。在語義版本控制下,版本號遵循major.minor.patch
的規(guī)則,版本號的增長遵循如下規(guī)則:
- major(主版本號)在API有不兼容的修改時增長
- minor(小版本號)以向后兼容的方式添加功能時增長
- patch(補丁)修改bug時增長
動態(tài)版本
某些情況下,你希望每次構(gòu)建應(yīng)用或者庫時都能獲得最新的依賴。最好的方式就是使用動態(tài)版本。下面是使用動態(tài)版本的幾種方式:
dependencies {
//獲取最新的patch
compile 'com.android.support:support-v4:22.2.+'
//獲取最新的小版本號至少是2的小版本
compile 'com.android.support:appcompat-v7:22.2+'
//獲取最新版本
compile 'com.android.support:recyclerview-v7:+'
}
你需要慎重使用動態(tài)版本。使用動態(tài)版本,Gradle可能會選擇不穩(wěn)定的版本,導(dǎo)致構(gòu)建失敗。更嚴重的是,構(gòu)建服務(wù)器和你的本地機器可能會使用不同版本的依賴,導(dǎo)致應(yīng)用的行為不一致。
在你使用動態(tài)版本時,Android Studio會給出警告。
Inside Android Studio
本節(jié)略過
依賴順序
配置文件中依賴的排列順序決定了優(yōu)先級的高低,排在前面的庫優(yōu)先級大于排在后面的庫。這個順序在資源合并和清單文件元素合并的時候非常重要。
比如,如果你的項目聲明如下:
- 依賴于A和B,且A在B前面
- A依賴于C和D,C在D前面
- B依賴于C
那么,展開的依賴順序如下:
- A
- D
- B
- C
這個順序保證了A和B都可以覆寫C;D的優(yōu)先級高于B,因為A的優(yōu)先級高于B。