一文完全搞清 Gradle 依賴

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

依賴類型

dependencies DSL標籤是標準Gradle API中的一部分,而不是Android Gradle插件的特性,因此它不屬於android標籤。正則表達式

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

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'
}
複製代碼

1. 本地library模塊依賴

implementation project(":mylibrary")
複製代碼

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

2. 本地二進制依賴

implementation fileTree(dir: 'libs', include: ['*.jar'])
複製代碼

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

若是隻想依賴單個特定本地二進制庫,能夠以下配置:app

implementation files('libs/foo.jar', 'libs/bar.jar')
複製代碼

3. 遠程二進制依賴

implementation 'com.example.android:app-magic:12.3'
複製代碼

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

implementation group: 'com.example.android', name: 'app-magic', version: '12.3'
複製代碼

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

依賴配置

目前Gradle版本支持的依賴配置有:implementationapicompileOnlyruntimeOnlyannotationProcessor,已經廢棄的配置有:compileprovidedapkprovidedCompile。此外依賴配置還能夠加一些配置項,例如AndroidTestImplementationdebugApi等等。gradle

經常使用的是implementationapicompileOnly三個依賴配置,含義以下:ui

implementation

與compile對應,會添加依賴到編譯路徑,而且會將依賴打包到輸出(aar或apk),可是在編譯時不會將依賴的實現暴露給其餘module,也就是隻有在運行時其餘module才能訪問這個依賴中的實現。使用這個配置,能夠顯著提高構建時間,由於它能夠減小從新編譯的module的數量。建議,儘可能使用這個依賴配置。

api

與compile對應,功能徹底同樣,會添加依賴到編譯路徑,而且會將依賴打包到輸出(aar或apk),與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任務,以下:

一、View -> Tools Windows -> Gradle或者點擊右側的Gradle欄);

二、展開 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'
}
複製代碼

三、禁用依賴傳遞

compile('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中排除和全局配置排除。



reference

相關文章
相關標籤/搜索