上篇文章咱们已经将Gradle基础运用介绍了一遍,能够这么说,只要你一直看了我这个Gradle系列,那么你的Gradle也将过关了,应对正常的工做开发已经不成问题了。java
这篇文章我要向你介绍的是关于如何使用Gradle来更加优雅的管理多个module之间的依赖关系。android
相信你必定有这样的经历:主项目依赖于多个子项目,或者项目间互相依赖。不一样子项目间的依赖的第三方库版本又没有进行统一,升级一个版本全部依赖的项目都要进行修改;甚至minSdkVersion与targetSdkVersion也不相同。git
今天咱们就来解决这个问题,让Gradle版本管理更加优雅。github
以前的文章Android Gradle系列-运用篇中的dependencies使用的是最基本的引用方式。若是你有新建一个kotlin项目的经历,那么你将看到Google推荐的方案api
buildscript { ext.kotlin_version = '1.1.51' repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.0.0' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } }
在rootProject的build.gradle中使用ext来定义版本号全局变量。这样咱们就能够在module的build.gradle中直接引用这些定义的变量。引用方式以下:app
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation"org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version" }
你能够将这些变量理解为java的静态变量。经过这种方式可以达到不一样module中的配置统一,但局限性是,一但配置项过多,全部的配置都将写到rootProject项目的build.gradle中,致使build.gradle臃肿。这不符合咱们的所提倡的模块开发,因此应该想办法将ext的配置单独分离出来。maven
这个时候我就要用到以前的文章Android Gradle系列-原理篇中所介绍的apply函数。以前的文章咱们只使用了apply三种状况之一的plugin(应用一个插件,经过id或者class名),只使用在子项目的build.gradle中。函数
apply plugin: 'com.android.application'
此次咱们须要使用它的from,它主要是的做用是应用一个脚本文件。做用接下来咱们须要作的是将ext配置单独放到一个gradle脚本文件中。gradle
首先咱们在rootProject目录下建立一个gradle脚本文件,我这里取名为version.gradle。ui
而后咱们在version.gradle文件中使用ext来定义变量。例如以前的kotlin版本号就可使用以下方式实现
ext.deps = [:] def versions = [:] versions.support = "26.1.0" versions.kotlin = "1.2.51" versions.gradle = '3.2.1' def support = [:] support.app_compat = "com.android.support:appcompat-v7:$versions.support" support.recyclerview = "com.android.support:recyclerview-v7:$versions.support" deps.support = support def kotlin = [:] kotlin.kotlin_stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jre7:$versions.kotlin" kotlin.plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:$versions.kotlin" deps.kotlin = kotlin deps.gradle_plugin = "com.android.tools.build:gradle:$versions.gradle" ext.deps = deps def build_versions = [:] build_versions.target_sdk = 26 build_versions.min_sdk = 16 build_versions.build_tools = "28.0.3" ext.build_versions = build_versions def addRepos(RepositoryHandler handler) { handler.google() handler.jcenter() handler.maven { url 'https://oss.sonatype.org/content/repositories/snapshots' } } ext.addRepos = this.&addRepos
由于gradle使用的是groovy语言,因此以上都是groovy语法
例如kotlin版本控制,上面代码的意思就是将有个kotlin相关的版本依赖放到deps的kotlin变量中,同时deps放到了ext中。其它的亦是如此。
既然定义好了,如今咱们开始引入到项目中,为了让全部的子项目都可以访问到,咱们使用apply from将其引入到rootProject的build.gradle中
buildscript { apply from: 'versions.gradle' addRepos(repositories) dependencies { classpath deps.gradle_plugin classpath deps.kotlin.plugin } }
这时build.gradle中就默认有了ext所声明的变量,使用方式就如dependencies中的引用同样。
咱们再看上面的addRepos方法,在关于Gradle原理的文章中已经分析了repositories会经过RepositoryHandler来执行,因此这里咱们直接定义一个方法来统一调用RepositoryHandler。这样咱们在build.gradle中就无需使用以下方式,直接调用addRepos方法便可
//以前调用 repositories { google() jcenter() } //如今调用 addRepos(repositories)
另外一方面,若是有多个module,例若有module1,如今就能够直接在module1中的build.gradle中使用定义好的配置
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // support implementation deps.support.app_compat //kotlin implementation deps.kotlin.kotlin_stdlib }
上面咱们还定义了sdk与tools版本,因此也能够一块儿统一使用,效果以下
android { compileSdkVersion build_versions.target_sdk buildToolsVersion build_versions.build_tools defaultConfig { applicationId "com.idisfkj.androidapianalysis" minSdkVersion build_versions.min_sdk targetSdkVersion build_versions.target_sdk versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } ... }
一旦实现了统一配置,那么以后咱们要修改相关的版本就只需在咱们定义的version.gradle中修改便可。无需再对所用的module进行逐一修改与统一配置。
若是你的项目使用了kotlin,那么buildSrc&Kotlin的统一管理方案将更适合你。
Gradle项目会默认识别buildSrc目录,而且会将该目录中的配置注入到build.gradle中,以致于让build.gradle可以直接引用buildSrc中的配置项。
有了这一特性,咱们就能够直接将以前version.gradle中的配置放入到buildSrc中,下面咱们开始实现。
首先在根目录新建一个buildSrc目录(与app同级),而后在该目录新建src/main/java目录,该目录是你以后配置项所在的目录;同时再新建build.gradle.kts文件,并在该文件中添加kotlin-dsl
plugins { `kotlin-dsl` } repositories { jcenter() }
以后再sync project,最终的目录结构以下
搭建好了目录,如今咱们在src/main/java下使用kotlin新建Dependencies文件(文件名任意),在该文件中将以前的配置项放进来,只是使用kotlin语法进行实现而已,转化的代码以下
object Versions { const val support = "26.1.0" const val kotlin = "1.3.31" const val gradle = "3.4.1" const val target_sdk = 26 const val min_sdk = 16 const val build_tools = "28.0.3" } object Dependencies { val app_compat = "com.android.support:appcompat-v7:${Versions.support}" val kotlin_stdlib = "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${Versions.kotlin}" val kotlin_plugin = "org.jetbrains.kotlin:kotlin-gradle-plugin:${Versions.kotlin}" val gradle_plugin = "com.android.tools.build:gradle:${Versions.gradle}" val addRepos: (handler: RepositoryHandler) -> Unit = { it.google() it.jcenter() it.maven { url = URI("https://oss.sonatype.org/content/repositories/snapshots") } } }
这时你就能够直接使用Dependencies与Versions在各个build.gradle中引用,例如app下的build.gradle
android { compileSdkVersion Versions.target_sdk buildToolsVersion Versions.build_tools defaultConfig { applicationId "com.idisfkj.androidapianalysis" minSdkVersion Versions.min_sdk targetSdkVersion Versions.target_sdk versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } ... } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) // support implementation Dependencies.app_compat //kotlin implementation Dependencies.kotlin_stdlib }
根目录的build.gradle亦是如此
buildscript { Dependencies.addRepos.invoke(repositories) dependencies { classpath Dependencies.gradle_plugin classpath Dependencies.kotlin_plugin } } allprojects { Dependencies.addRepos.invoke(repositories) } task clean(type: Delete) { delete rootProject.buildDir }
其实咱们真正须要get到的是一种思想,将配置统一管理。至于到底使用哪种,这就看我的喜爱了,但若是你的项目使用了kotlin,我仍是建议你使用buildSrc模式,由于对于Groovy语法而言,我相信你仍是对Kotlin更加熟悉。
源码地址: https://github.com/idisfkj/an...
若是想了解更多关于个人文章,能够扫描下方二维码,关注个人公众号~