一、 Gradle 的依賴包
在使用 eclipse 做專案的使用,如果要使用別人的庫,要麼clone工程到自己專案再新增依賴,或者匯出為jar包引入,或者直接去找jar再新增到專案路徑(add to path)。而使用maven,將查詢下載jar這個過程簡化,直接通過 dependency 指定依賴庫名、版本,接著自動從maven下載並新增到專案中。
二、 Gradle 除了引用線上倉庫版本,還可以使用本地模組依賴,離線 aar 和 jar 庫,請問 aar 和 jar 有什麼區別?
jar 只有 class 檔案和清單檔案,不包含資原始檔,如圖片 aar 包含所有資源,class 以及 res 資原始檔,如圖片,strings.xml 等
使用:
- jar 檔案複製到 libs 目錄,eclipse 直接匯入右鍵 add to path,AndroidStudio 新增依賴如下
dependencies{//選擇一個即可
//新增 libs 目錄下所有 jar
implementation fileTree(include: ['*.jar'], dir: 'libs')
//新增直接指定 jar
implementation files('libs/xx.jar')
}
複製程式碼
- 使用 aar,分兩種,本地及遠端倉庫
//遠端倉庫
dependencies{
implementation 'com.android.support:appcompat-v7:28.0.1'
}
//本地 aar,將aar放在專案目錄中,如在libs,在module的 build.gradle中新增
repositories{//新增本地倉庫
flatDir{//指定倉庫路徑
dirs 'libs'
}
}
dependencies{
implementation (name:'xxx',ext:'aar')
}
複製程式碼
三、 Gradle 專案中,使用遠端倉庫,依賴庫 A 引用庫 B:1.0.0,專案依賴 B:1.2.0 ,是否會發生衝突,最終打包依賴 B 版本是哪個?如果A引用B:3.0.0呢?
分三種情況:
- A 依賴 B 時,使用jar形式,將 B 原始碼打包進 A 編譯時沒有問題,打包提示資源重複,打包失敗
- A 依賴 B 時,使用jar形式,但沒有將 B 原始碼打包進 A 沒有問題,直接使用專案中依賴指定的版本,與 A 引用的 B 版本無關,可以說庫 A 中的 B 不存在
- A 依賴 B 時,使用遠端倉庫的依賴 沒有問題,出現版本號不一致,均使用最高版本號作為最終版本
以 Retrofit 和 OkHttp 為例,看看遠端倉庫依賴
注:Retrofit:2.5.0,OkHttp:3.12.0,okio:1.15.0
-
只引入 Retrofit 同步後專案截圖:
簡單測試一下介面,可用
-
手動引入 OkHttp:3.12.1 高版本,會點選同步
-
降低版本試試,同步一下
這裡,Gradle 對比引用依賴庫版本,使用最高的版本作為專案使用的最終版本。 指定使用依賴庫低版本時,在 gradle 中提示 “A newer version of com.squareup.okhttp3:okhttp than 3.10.0 is available: 3.14.0” 更多資訊
This detector looks for usages of libraries where the version you are using is not the current stable release. Using older versions is fine, and there are cases where you deliberately want to stick with an older version. However, you may simply not be aware that a more recent version is available, and that is what this lint check helps find. 意思是有更高的版本,但是你要使用低版本也沒有問題,他僅僅是編譯器檢查告知我們有更新的版本可以使用,最後使用的也是高版本。
- 如果,我非要使用我指定的低版本使用,該怎麼寫依賴? 使用exclude去除版本依賴,程式碼如下:
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation('com.squareup.retrofit2:retrofit:2.5.0') {
exclude (group: 'com.squareup.okhttp3' ,module: 'okhttp')
}
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
}
複製程式碼
同步後,專案
結論: 從上面也可以看出來,遠端依賴,一般不會出現重複依賴的問題,因為在比對版本後,會統一使用更高版本,這裡也引出一個知識點,就是遠端依賴其實沒有把依賴的庫的程式碼打包在一起,各自彼此獨立,只是我要引用到你的庫,才會去倉庫把你下載下來,依賴可以理解為名義上的關係。
四、依賴庫重複打包失敗舉例,上面第一種情況舉例,以 Retrofit:2.5.0 和 cn.bmob.android:bmob-sdk:3.5.1
有時也會發現,我們依賴庫,會出現庫衝突,也就是
org.gradle.api.tasks.TaskExecutionException: Execution failed for task':app:transformDexArchiveWithExternalLibsDexMergerForRelease'.
具體如下:
首先編譯安全通過:
但是,打包失敗!!
雙擊 Run Tasks 檢視異常,提示合併失敗,我們檢視引用庫,發現 bmob 是將 OkHttp、okio 以jar包形式引入,即 bmob庫擁有 OkHttp、okio 原始碼,我們專案的 Retrofit 引用 OkHttp、okio 又下載了這兩個庫原始碼,所以存在兩個不同版本的 okhttp、okio,所以打包重複資源合併失敗。 解決方案,移除任何一方的庫,使用 exclude,但需注意的是,如果原始碼以jar包形式存在則無法使用 exclude 去除,只能移除遠端倉庫依賴部分。
五、編寫庫,注意依賴打包問題
所以在編寫庫的時候,一般依賴其他庫時,能用遠端庫最好,不能的話使用jar時,如果不是特別難找的包,可以使用compileOnly(老版本provided)宣告jar包只用於編譯階段,打包不將jar打包進自己的庫。
三種不同依賴,打包後具體如下:
-
使用遠端倉庫依賴,生成aar不會打包引用的庫原始碼
-
使用jar,用 implementation,會把 jar 引入生成的aar中
-
使用jar,用 compileOnly,jar 原始碼不打包進aar中,這種模式下,如果引用的人沒有再引入對應的jar包,那麼會執行錯誤,NoClassDefFoundError 注意
五、出現重複依賴或版本不一致處理方案
使用 exclude 去除,缺點如果存在多個會找到吐血,逐個新增去除
dependencies{
//本地 aar,但對依賴進的 jar 無效
implementation (name:'xxx',ext:'aar'){
exclude(group: 'com.alibaba', module: 'fastjson')
}
//遠端倉庫
implementation ('xxx:xx:1.0.0'){
exclude(group: 'com.alibaba', module: 'fastjson')
}
}
複製程式碼
或者直接通過全域性配置,去除指定遠端倉庫,除非專案不需要這個庫,否則不要使用這個方法,缺點如果要用,自己也沒有辦法用
configurations.all {
exclude(group: 'com.alibaba', module: 'fastjson')
}
複製程式碼
也可以通過全域性配置,修改依賴庫為指定版本,可以說是最佳方案了
configurations.all {
resolutionStrategy.eachDependency { DependencyResolveDetails details ->
def requested = details.requested
if (requested.group == 'com.alibaba'&& requested.name == 'fastjson') {
details.useVersion '1.2.56'
}
}
}
複製程式碼
好了,本文依賴部分就到這裡結束啦!謝謝閱讀。
已開通微信公眾號碼農茅草屋,有興趣可以關注,一起學習