Android studio 来自通过Gradle 做为一个构建和打包android工程的工具,这个强大的工具,非常有用,能够提供很多强大,满足开发复杂android工程。这些工程可能包含不同的module,变量,依赖,连续延伸的系统,代码质量等。
这篇文章的动机只是分享一下Gradle我在自己工程上的应用.项目工程实例地址
Working with flavors
flavors 中文翻译是风味调料的意思,动词就是添加味道的意思。假如,在我们的工程中有三个flavors,一个叫做 free flavor,另一个叫做 paid flavor,最后一个叫做 promob flavor.
productFlavors {
paid {}
free {}
promo {}
}
为了配置他们,我们不是直接在 android module里的 build.gradle 里写,我们有一个新的分离的文件叫做 variants.gradle 每个flavor拥有不同的属性。
/vaivariants.gradle
ext {
basePackageName = 'adamin1990.gradlestuff'
resAppColorName = 'build_brand_primary'
resAppName = 'build_app_name'
fieldShowAds = 'ADS'
paid = [
packageName : "${basePackageName}.premium",
appName : "Gradle Stuff Premium",
appColor : "#F44336",
showAds : "false",
versionName : "2.3.2",
versionCode : 4
]
free = [
packageName : "${basePackageName}.free",
appName : "Gradle Stuff",
appColor : "#4CAF50",
showAds : "true",
versionName : "4.1.1",
versionCode : 15
]
promo = [
packageName : "${basePackageName}.promo",
appName : "Gradle Stuff Demo",
appColor : "#9C27B0",
showAds : "true",
versionName : "1.0",
versionCode : 1
]
这个文件将用在project根目录的 build.gradle 中 ,此时子module就可以利用这些属性了。
/build.gradle
apply from: 'variants.gradle'
variants.gradle 中 ext{} 内的属性可以用下面的方法访问: rootProject.ext.{field}
/ {android module} / build.gradle
productFlavors {
paid {
def paid = rootProject.ext.paid
applicationId paid.packageName
buildConfigField 'boolean', fieldShowAds, paid.showAds
resValue 'string', resAppName, paid.appName
resValue 'color', resAppColorName, paid.appColor
}
free {
def free = rootProject.ext.free
applicationId free.packageName
buildConfigField 'boolean', fieldShowAds, free.showAds
resValue 'string', resAppName, free.appName
resValue 'color', resAppColorName, free.appColor
}
promo {
def promo = rootProject.ext.promo
applicationId promo.packageName
buildConfigField 'boolean', fieldShowAds, promo.showAds
resValue 'string', resAppName, promo.appName
resValue 'color', resAppColorName, promo.appColor
}
}
每一个flavor,Android分配特定的文件夹有不同的特定资源或flavor class,我们可能为某个单独的文件替换 variants.gradle 内的值,对我来说,更清楚的将一切集中在一个地方了。
此时,假设我们有更多的flavor:
/ presentation / build.gradle
productFlavors {
paid {
def paid = rootProject.ext.paid
applicationId paid.packageName
buildConfigField 'boolean', fieldShowAds, paid.showAds
resValue 'string', resAppName, paid.appName
resValue 'color', resAppColorName, paid.appColor
}
free {
def free = rootProject.ext.free
applicationId free.packageName
buildConfigField 'boolean', fieldShowAds, free.showAds
resValue 'string', resAppName, free.appName
resValue 'color', resAppColorName, free.appColor
}
promo {
def promo = rootProject.ext.promo
applicationId promo.packageName
buildConfigField 'boolean', fieldShowAds, promo.showAds
resValue 'string', resAppName, promo.appName
resValue 'color', resAppColorName, promo.appColor
}
christmas {
def christmas = rootProject.ext.christmas
applicationId christmas.packageName
buildConfigField 'boolean', fieldShowAds, christmas.showAds
resValue 'string', resAppName, christmas.appName
resValue 'color', resAppColorName, christmas.appColor
}
halloween {
def halloween = rootProject.ext.halloween
applicationId halloween.packageName
buildConfigField 'boolean', fieldShowAds, halloween.showAds
resValue 'string', resAppName, halloween.appName
resValue 'color', resAppColorName, halloween.appColor
}
easter {
def easter = rootProject.ext.easter
applicationId easter.packageName
buildConfigField 'boolean', fieldShowAds, easter.showAds
resValue 'string', resAppName, easter.appName
resValue 'color', resAppColorName, easter.appColor
}
independence {
def independence = independence.ext.christmas
applicationId christmas.packageName
buildConfigField 'boolean', fieldShowAds, independence.showAds
resValue 'string', resAppName, independence.appName
resValue 'color', resAppColorName, independence.appColor
}
}
module中 build.gradle文件就会变长并且重复,如果我们查看 Android Gradle 插件 DSL ,我们会发现 productFlavors 委派de 类;NamedDomainObjectContainer 提供了一个 whenObjectAdded 方法允许大概对象加入时执行一个动作,在“ProductFlavor” 情况下:
/ presentation / build.gradle
productFlavors.whenObjectAdded { flavor ->
def flavorData = rootProject.ext[flavor.name]
flavor.applicationId paid.packageName
flavor.buildConfigField
'boolean', fieldShowAds, flavorData.showAds
flavor.resValue
'string', resAppName, flavorData.appName
flavor.resValue
'color', resAppColorName, flavorData.appColor
}
用这种方法,我们可以重构flavor
/ presentation / build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion androidSdkVersion
buildToolsVersion androidToolsVersion
defaultConfig {
applicationId basePackageName
minSdkVersion androidMinSdkVersion
targetSdkVersion androidSdkVersion
}
buildTypes {
debug {
applicationIdSuffix '.debug'
}
}
productFlavors.whenObjectAdded { flavor ->
def flavorData = rootProject.ext[flavor.name]
flavor.applicationId flavorData.packageName
flavor.buildConfigField
'boolean', fieldShowAds, flavorData.showAds
flavor.resValue
'string', resAppName, flavorData.appName
flavor.resValue
'color', resAppColorName, flavorData.appColor
}
productFlavors {
paid {}
free {}
promo {}
christmas {}
halloween {}
easter {}
independence {}
}
}
Working with modules
使用独立的模块,使工程澄清,特别是一个组件分层的特殊结构。
module在 setting.gradle 中声明,它指明了哪一部分将是功能的部分
include ':presentation', ':domain', ':model'
我们需要知名哪一个module是作为依赖module,举个例子,如果我们在 presentation module 并且我们需要 domain module 里面的类,此时我们需要编译domain 工程:
dependencies {
compile project (':domain')
}
Dependencies
这里,给出了一个极好的处理 dependencies的方法,在本文的例子中,我们在工程根目录有一个 dependencies.gradle 文件 规定(stipulate)了每个module用到的依赖。
顺便说下, .gralde 文件可以在任何文件夹下创建,总是指明了所需路径。
/ dependencies.gradle
ext {
butterKnifeVersion = '7.0.1'
recyclerViewVersion = '21.0.3'
supportLibrary = '22.2.0'
firebase = '2.3.1'
rxAndroidVersion = '0.25.0'
rxJavaVersion = '1.0.10'
presentationDependencies = [
butterKnife :
"com.jakewharton:butterknife:$butterKnifeVersion",
recyclerView :
"com.android.support:recyclerview-v7:$supportLibrary",
cardView :
"com.android.support:cardview-v7:$supportLibrary",
appCompat :
"com.android.support:appcompat-v7:$supportLibrary",
supportAnnotation:
"com.android.support:support-annotations:$supportLibrary",
rxAndroid :
"io.reactivex:rxandroid:$rxAndroidVersion",
rxJava :
"io.reactivex:rxjava:$rxJavaVersion",]
domainDependencies = [
rxJava: "io.reactivex:rxjava:${rxJavaVersion}",]
modelDependencies = [
fireBase: "com.firebase:firebase-client-android:$firebase",
rxJava : "io.reactivex:rxjava:$rxJavaVersion",]
}
这个文件也要在工程根目录的 build.gradle 里应用
/ build.gradle
apply from: 'dependencies.gradle'
/ presentation / build.gradle
apply plugin: 'com.android.application'
android {
dependencies {
def presentationDependencies =
rootProject.ext.presentationDependencies
compile presentationDependencies.butterKnife
compile presentationDependencies.recyclerView
compile presentationDependencies.appCompat
compile presentationDependencies.supportAnnotation
compile presentationDependencies.rxAndroid
compile presentationDependencies.rxJava
}
}