原文地址:https://hackernoon.com/android-how-to-add-gradle-dependencies-using-foreach-c4cbcc070458#.mqxce4ehy
如果一個大的android項目中有幾個modules并且有多個Gradle文件需要配置的話,是一個神煩的任務(wù),通常要做的是向每個模塊添加依賴項,在本篇文章中將介紹如何使用一個Gradle文件來控制所有模塊的依賴項。
我們的目標是將如下的文件:
dependencies {
compile ‘com.android.support:appcompat-v7:24.2.0’
compile ‘com.google.dagger:dagger:2.7’
apt ‘com.google.dagger:dagger-compile:2.7’
compile ‘io.reactivex:rxjava:1.2.0’
compile ‘io.reactivex:rxandroid:1.2.1’
compile ‘com.squareup.okhttp3:okhttp:3.4.1’
compile ‘com.google.code.gson:gson:2.7’
testCompile ‘junit:junit:4.12’
}
轉(zhuǎn)換成如下:
dependencies {
rootProject.appDependencies.each {
add(it.configuration, it.dependency, it.options)
}
}
Dependencies File
為了完成這個轉(zhuǎn)換,首先創(chuàng)建一個文件來管理項目依賴
創(chuàng)建一個文件denpendencies.gradle在項目的根目錄下,然后定義所有用到的library的版本號。
ext{
def versionAndroidSDK = '24.2.0'
def versionDagger = '2.7'
def versionRxJava = '1.2.0'
def versionRxAndroid = '1.2.1'
def versionOkHttp = '3.4.1'
def versionGson = '2.7'
def versionJUnit = '4.12'
}
一旦完成,讓我們創(chuàng)建依賴映射,為了使文件盡量有組織,將定義三個map,一個用于Android官方庫,一個用于第三方庫,最后一個用于測試庫。
看一下文件的樣子:
ext {
//...
///
/// LIBS
///
def androidLibs = [
appCompat : [group: 'com.android.support', name: 'appcompat-v7', version: versionAndroidSDK]
]
def libs = [
dagger: [group: 'com.google.dagger', name: 'dagger', version:versionDagger],
daggerCompiler: [group: 'com.google.dagger', name: 'dagger-compiler', version:versionDagger],
rxAndroid: [group: 'io.reactivex', name: 'rxandroid', version: versionRxAndroid],
rxJava: [group: 'io.reactivex', name: 'rxjava', version: versionRxJava],
rxOkHttp: [group: 'com.squareup.okhttp3', name: 'okhttp', version: versionOkHttp],
gson: [group: 'com.google.code.gson', name: 'gson', version: versionGson],
]
def testLibs = [
junit: [group: 'junit', name: 'junit', version: versionJUnit]
]
}
現(xiàn)在每個模塊都需要包含一個所有依賴項的列表。
作為一個示例,app模塊將會使用到所定義的AppCompat,Dagger,RxJava
和RxAndroid,如下列表所示:
ext {
// Versions
/// Libs
/// Modules dependencies
appDependencies = [
[configuration: "compile", dependency: androidLibs.appCompat],
[configuration: "compile", dependency: libs.dagger],
[configuration: "apt", dependency: libs.daggerCompiler],
[configuration: "compile", dependency: libs.rxAndroid],
[configuration: "compile", dependency: libs.rxJava],
]
}
列表中的每一個對象,都包含一個定義依賴關(guān)系的映射及其配置,在這個例子中使用了compile和apt配置,但是還有很多,如“provided”,“testCompile”,“androidTestCompile”,等等。
現(xiàn)在打開app模塊的gradle文件,并且使用如下代碼:
dependencies{
rootProject.appDependencies.each{
add(it.configuration,it.dependency)
}
}
這是如何工作的?
通常我們添加一個依賴項如下所示:
compile 'com.google.code.gson:gson:2.7'
DependencyHandle對象添加方法會被直接調(diào)用,讓我們看一下這個添加方法:
add(String configurationName,Object dependencyNotation)
向給定配置添加依賴關(guān)系
這兩個方法接受兩個參數(shù),第一個是配置名稱(compile,testCompile,androidTestCompile),第二個參數(shù)是依賴本身。
Dependency可以按照常規(guī)方式定義為一個String變量。
'com.google.code.gson:gson:2.7'
如果使用最新的gradle版本的話,可以被定義成一個Map。
[group:'com.google.code.gson',name:'gson',version:'2.7']
回到代碼:
dependencies{
rootProject.appDependencies.each{
add(it.configuration,it.dependency)
}
}
appdependencies列表在迭代之前創(chuàng)建,每次迭代都添加一個依賴項及其配置,it表示在迭代中表示當前元素。
這個過程需要在每個build.gradle文件中重復(fù)進行,這樣當需要新的依賴時只需要把依賴添加到依賴文件中相應(yīng)的集合中,這樣,所有的依賴關(guān)系只用控制這一個文件中,此文件將可以在其他Android項目中重復(fù)使用。
模塊之間的依賴
可以用于添加模塊之間的依賴項
要這樣做,需要在dependencies.gradle文件中定義所有模塊,比如,app、data和domain模塊。
{
/// Versions
/// Libs
/// Module dependencies
///
/// Modules
///
def modules = [
app: ':app',
data: ':data',
domain: ':domain'
]
}
如果app模塊要使用domain模塊的話,那么dependency需要按如下方式添加:
ext {
// Versions
/// Libs
/// Modules dependencies
appDependencies = [
[configuration: "compile", dependency: androidLibs.appCompat],
[configuration: "compile", dependency: libs.dagger],
[configuration: "apt", dependency: libs.daggerCompiler],
[configuration: "compile", dependency: libs.rxAndroid],
[configuration: "compile", dependency: libs.rxJava],
// Domain dependency
[configuration: "compile", dependency: project(modules.domain)],
]
}
可選項
如果需要任何其他選項,例如排除模塊或使用可傳遞,常規(guī)的方法是:
androidTestCompile ('com.android.support.test:runner:0.5'){
exclude module:'support-annotations'
}
首先要做的是,在依賴中添加一個額外的鍵值來表示選項。讓我們看一個例子:
// Exclude example
[configuration: "androidTestCompiler", dependency: testRunner,
options: { exclude module: 'support-annotations'}]
現(xiàn)在app模塊中的build.gradle文件中需要修改并且更改add方法,因此他添加一個閉包作為一個額外的參數(shù)以添加選項:
add(String configurationName,Object dependencyNotation,Closure configurationClosure)
向給定配置添加依賴關(guān)系,并使用給定的閉包配置依賴關(guān)系。
build.gradle文件看起來如下:
dependencies{
rootProject.addDependencies.each{
add(it.configuration, it.dependency, it.options)
}
}
插件
有了這個過程,我們也可以管理,我們在每個模塊中使用的插件,并通過dependencies.gradle文件來控制所有的插件,讓我們看一個例子:
apply plugin:'com.neebedankt.android-apt'
apply plugin:'realm-android'
apply plugin:'com.tatarka.retrolambda'
可以用如下替換:
rootProject.appPlugins.each{
apply plugin.it
}
只需要創(chuàng)建一個列表,該插件將有dependencies.gradle文件中的模塊使用。
ext {
/// Versions
/// Libs
/// Modules Dependencies
/// Modules
/// Plugins
appPlugins = [
'com.neenbedankt.android-apt',
'realm-android',
'me.tatarka.retrolambda'
]
}
調(diào)用dependencies.gradle
以上所有過程得以調(diào)用完全依賴于在項目根路徑下的build.gradle文件中調(diào)用dependencies.gradle文件
apply from: 'dependencies.gradle'
缺點
在這個過程中并非一切都是完美的,這種添加管理依賴的方式使得Android Studio在庫過時的時候得到通知。
為了解決這個問題,可以使用常規(guī)方法和此方法共同管理,Android原生庫使用常規(guī)方法管理以便在過時的時候接收到通知。
dependencies {
compile "com.android.support:appcompat-v7:$rootProject.versionAndroidSDK"
rootProject.appDependencies.each {add(it.configuration, it.dependency, it.options)
}
}