當前位置:
首頁 > 知識 > 一文搞清Gradle依賴

一文搞清Gradle依賴

(給

ImportNew

加星標,提高Java技能)


轉自:曾是放牛娃


https://www.jianshu.com/p/59fd653a54d2

之前對 Android Gradle 構建的依賴一直傻傻分不清,這段時間正好接入集團的一個二方庫,踩了很多坑,也順帶把 Gradle 依賴這塊搞清楚了。主要整理了下 Gradle 依賴的類型、依賴配置、如何查看依賴、依賴衝突如何解決。



依賴類型



dependencies DSL 標籤是標準 Gradle API 中的一部分,而不是 Android Gradle 插件的特性,所以它不屬於 Android 標籤。

依賴有三種方式,如下面的例子:


apply plugin:

"com.android.application"

android { ... }

dependencies {
   

// Dependency on a local library module


   implementation project(

":mylibrary"

)

   

// Dependency on local binaries


   implementation fileTree(dir:

"libs"

,

include

: [

"*.jar"

])

   

// Dependency on a remote binary

   implementation

"com.example.android:app-magic:12.3"


}

本地 library 模塊依賴

implementation

project(

":mylibrary"

)

這種依賴方式是直接依賴本地庫工程代碼的(需要注意的是,mylibrary 的名字必須匹配在 settings.gradle 中 include 標籤下定義的模塊名字)。


本地二進位依賴


implementation

fileTree(dir:

"libs"

, include: [

"*.jar"

])

這種依賴方式是依賴工程中的 module_name/libs/ 目錄下的 Jar 文件(注意 Gradle 的路徑是相對於 build.gradle 文件來讀取的,所以上面是這樣的相對路徑)。



如果只想依賴單個特定本地二進位庫,可以如下配置:


implementation

files(

"libs/foo.jar"

,

"libs/bar.jar"

)

遠程二進位依賴

implementation

"com.example.android:app-magic:12.3"

上面是簡寫的方式,這種依賴完整的寫法如下:

implementation

group

:

"com.example.android"

, name:

"app-magic"

, version:

"12.3"

group、name、version共同定位一個遠程依賴庫。需要注意的點是,version最好不要寫成」12.3+」這種方式,除非有明確的預期,因為非預期的版本更新會帶來構建問題。遠程依賴需要在repositories標籤下聲明遠程倉庫,例如jcenter()、google()、maven倉庫等。



依賴配置



目前 Gradle 版本支持的依賴配置有:implementation、api、compileOnly、runtimeOnly 和 annotationProcessor。已經廢棄的配置有:compile、provided、apk、providedCompile。此外依賴配置還可以加一些配置項,例如 AndroidTestImplementation、debugApi 等等。


常用的是 implementation、api、compileOnly 三個依賴配置,含義如下:





  • implementation:與compile對應,會添加依賴到編譯路徑,並且會將依賴打包到輸出(aar或apk),但是在編譯時不會將依賴的實現暴露給其他module,也就是只有在運行時其他module才能訪問這個依賴中的實現。使用這個配置,可以顯著提升構建時間,因為它可以減少重新編譯的module的數量。建議,盡量使用這個依賴配置。



  • api:與 compile 對應,功能完全一樣,會添加依賴到編譯路徑,並且會將依賴打包到輸出(aar 或a pk)。與 implementation 不同,這個依賴可以傳遞,其他 module 無論在編譯時和運行時都可以訪問這個依賴的實現,也就是會泄漏一些不應該不使用的實現。舉個例子,A 依賴 B,B 依賴 C,如果都是使用 api 配置的話,A 可以直接使用 C 中的類(編譯時和運行時)。而如果是使用 implementation 配置的話,在編譯時,A 無法訪問 C 中的類。



  • compileOnly:與 provided 對應,Gradle 把依賴加到編譯路徑,編譯時使用,不會打包到輸出(aar 或 apk)。這可以減少輸出的體積,在只在編譯時需要,在運行時可選的情況,很有用。



  • runtimeOnly:與 apk 對應。Gradle添加依賴只打包到 apk,運行時使用,但不會添加到編譯路徑。這個沒有使用過。



  • annotationProcessor:與 compile 對應,用於註解處理器的依賴配置,這個沒用過。



查看依賴樹



可以查看單個module或者這個project的依賴,通過運行依賴的 Gradle 任務,如下:




  1. View -> Tools Windows -> Gradle(或者點擊右側的 Gradle 欄);



  2. 展開 AppName -> Tasks -> Android,然後雙擊運行 AndroidDependencies。運行完,就會在 Run 窗口打出依賴樹了。



依賴衝突解決



隨著很多依賴加入到項目中,難免會出現依賴衝突,出現依賴衝突如何解決?



定位衝突



依賴衝突可能會報類似下面的錯誤:

Program

type

already

present

com

.example.MyClass

通過查找類的方式(command + O)定位到衝突的依賴,進行排除。



如何排除依賴



dependencies 中排除(細粒度)


compile(

"com.taobao.android:accs-huawei:1.1.2@aar"

) {
       transitive =

true


       exclude

group

:

"com.taobao.android"

, module:

"accs_sdk_taobao"


}

全局配置排除


configurations {
   compile.exclude

module

:

"cglib"


   

//全局排除原有的tnet jar包與so包分離的配置,統一使用aar包中的內容


   all*.exclude group:

"com.taobao.android"

,

module

:

"tnet-jni"


   all*.exclude group:

"com.taobao.android"

,

module

:

"tnet-so"


}

禁用依賴傳遞


ompile(

"com.zhyea:ar4j:1.0"

) {
   transitive =

false


}

configurations.all {
   transitive =

false


}

還可以在單個依賴項中使用 @jar 標識符忽略傳遞依賴:


compile

"com.zhyea:ar4j:1.0

@jar

"

強制使用某個版本



如果某個依賴項是必需的,而又存在依賴衝突時,此時沒必要逐個進行排除,可以使用force屬性標識需要進行依賴統一。當然這也是可以全局配置的:


compile(

"com.zhyea:ar4j:1.0"

) {
   force =

true


}

configurations.all {
   resolutionStrategy {
       force

"org.hamcrest:hamcrest-core:1.3"


   }
}

在打包時排除依賴



先看一個示例:


task

zip

(

type: Zip

)

{
    

into

(

"lib"

) {
        

from

(configurations.runtime) {
            exclude

"*unwanted*"

,

"*log*"


        }
    }
    

into

(

""

) {
        

from

jar
        

from

"doc"


    }
}

代碼表示在打 zip 包的時候會過濾掉名稱中包含 「unwanted」 和 「log」 的 jar 包。這裡調用的 exclude 方法的參數和前面的例子不太一樣,前面的參數多是 map 結構,這裡則是一個正則表達式字元串。



也可以使用在打包時調用 include 方法選擇只打包某些需要的依賴項:

task

zip

(

type: Zip

)

{
   

into

(

"lib"

) {
       

from

(configurations.runtime) {
           include

"*ar4j*"

,

"*spring*"


       }
   }
   

into

(

""

) {
       

from

jar
       

from

"doc"


   }
}

主要是使用 dependencies 中排除和全局配置排除。




看完本文有收穫?請轉發分享給更多人


關注「ImportNew」,提升Java技能



喜歡就點「好看」唄~



喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ImportNew 的精彩文章:

從 Spring Cloud 看一個微服務框架的「 五臟六腑 」
淺析幾種線程安全模型

TAG:ImportNew |