Gradle for Android(三) 依賴管理

依賴管理是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'
}

一個依賴的必需元素是namegroupversion是可選的。盡管如此,我們?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/m2repositoryANDROID_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中,不會包含在類路徑中。

providedapk相反。這兩種配置只接受JAR依賴項,試圖將庫工程加入其中會導(dǎo)致錯誤。

testCompileandroidTestCompile會添加測試所需的特定外部庫。這兩個配置可以添加測試框架,比如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

那么,展開的依賴順序如下:

  1. A
  2. D
  3. B
  4. C

這個順序保證了A和B都可以覆寫C;D的優(yōu)先級高于B,因為A的優(yōu)先級高于B。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,936評論 6 535
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,744評論 3 421
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,879評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,181評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,935評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,325評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,384評論 3 443
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,534評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,084評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 40,892評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,067評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,623評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,322評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,735評論 0 27
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,990評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,800評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,084評論 2 375

推薦閱讀更多精彩內(nèi)容