笔者最近接受了 躺平
(不是等死),换了一份新工做。html
这部份内容,也是从前东家的 实际状况
出发的,惋惜没法亲手去推广落地了。java
在前段时间,我发布过一篇拙见:三思系列:组件化场景下module依赖优雅实践方案, 该文在组件化背景下,探索了一种方案,能够同时知足 减小编译数量以减小编译时间
、便捷的修改依赖树以灵活改动任意层级的Module内容
。 具体内容能够阅读前文,再也不赘述android
除却Module依赖,还有 库包依赖
,本文着重于探索 库包依赖项
的管理方式,并且是狭义上的 仓库下的库包
编程
并 斗胆
称之为 最佳实践
。后端
首先肯定一件事情:markdown
implementation fileTree(dir: 'libs', include: ['*.jar'])
复制代码
此类方式,引入的库包不属于 仓库
范畴,仅讨论基于Maven仓库的范畴,赘述一句,仓库按照习惯又能够分为两种类型:网络
固然,这并不影响本文的讨论app
众所周知,使用Gradle肯定仓库的库包须要三个因素:框架
最新
的含义for example:运维
androidx.core:core-ktx:1.3.2
复制代码
以Android为例,商业项目中,一个Project仅存在一个Module
的状况应该 很是少见 了, 每每一个Project下会存在多个Module,并且存在必定的依赖关系。
若是没有合适的管理手段,那么每一个Module均声明自身的依赖项,当发生版本变动时:
修改过于零碎
同一个依赖项在不一样Module下可能出现版本差别
,这也是上一点所带来的后果
举个更典型的例子,以 后端项目为例,微服务
的概念你们必定不陌生.
即便不曾深刻了解,也知道后端将整个服务体系进行了拆分,用多个子系统项目(微服务)共同 支撑完整的服务体系。 以此达到 下降复杂度、 根据业务特性使用不一样框架、 根据业务权重定制运维策略 等目的
而微服务之间经过RPC进行通讯,而此处势必牵涉一个最大的 痛点
:Service方法签名和DTO数据保持一致
,不然会带来 方法不存在
或者 数据遗失、解析错误
等问题。
比较早期的作法,是在Gradle构建时的运行环境中,建立或者利用Project级别的集合对象,将依赖项信息所有写入其中,各个Module使用时,达成了统一。
你们对这种作法很熟悉,再也不用代码举例。 每每须要用到Extension扩展,为了方便描述,咱们将:存储依赖项信息的Project级别集合
称为 Ext.deps
优势:
缺点:
新版本提示
利用Gradle 能够apply 远程构建脚本 (xxx.gradle) 的特性,进行方案改进。
将 "构建 Ext.deps 信息" 的 脚本
,存储于网络特定位置,以解决多Project难以管理的问题。
通常须要对脚本文件按照版本命名,并保有全部版本的脚本。
这样能够避免:项目回溯版本功能时,出现额外问题。
Gradle编译项目是颇有意思的事情,咱们知道:在成功加载完Gradle项目后,会 编译Gradle脚本
并生成各种Gradle任务,实际状况会更加复杂,为了方便,咱们将之称为 Task编译
既然存在编译过程,Gradle团队索性留了一个后门:
若是根项目下存在"buildSrc", gradle 认为这是在Task编译过程当中须要编译的内容,这些内容可能包含了:
- Gradle插件内容
- 插件设置内容
- 等等
而且其编译结果对于该项目下的Gradle内容透明
这并非一个新的特性,它至少已经有五年的历史了
Gradle官方指导文档 ,官方文档对其使用方式作了概要的描述。
由于buildSrc机制已经不是一个新特性了,故而利用这个机制去 管理Gradle依赖信息
已是一个老话题了。
多是巧合
,该作法出如今开发者视野中时,恰好是 gradle开始对 kotlin-dsl
进行支持,一样不是新特性,大约是三年前的Gradle-4.10。
而开始流行的作法又刚好对新特性进行了尝鲜,而且在讲解视频中留下了一些坑,因而这一作法的着重点,便被吸引到了 如何正确使用kotlin管理Gradle项目的依赖项
这一话题上。
这一作法和kotlin、kts脚本并没有实质关联
在buildSrc目录下,按照标准sourceSet结构创建目录,并新增类文件例如:
buildSrc/src/main/java/Deps.java
public class Deps {
public static String junit = "junit:junit:4.13.0";
}
复制代码
sync后,类会被编译,咱们能够在项目下的Gradle脚本中,只用使用,例如:
dependencies {
//...
testImplementation Deps.junit
// 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
复制代码
而且能够享有 代码提示
、 跳转
、 javaDoc弹窗
功能
而可查询到的常见作法,每每是使用kotlin类,那么就须要让buildSrc 在编译时支持kotlin
,那么天然须要 添加插件
:
在buildSrc下新建 build.gradle
并添加插件:
apply plugin: "kotlin"
buildscript {
ext.kotlin_version = "1.4.21"
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
repositories {
jcenter()
}
复制代码
便可,此时添加的kotlin类便可被编译。
buildSrc/src/main/java/KDeps.kt
object KDeps {
@JvmStatic
val ext_junit = "androidx.test.ext:junit:1.1.2"
}
复制代码
使用示例:
dependencies {
testImplementation Deps.junit
// 'junit:junit:4.+'
androidTestImplementation KDeps.ext_junit
//'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
复制代码
一样能够享有 代码提示
、 跳转
、 javaDoc弹窗
功能
而网传的 kts脚本
以及添加 kotlin-dsl
支持,其实在这个需求中,并没有真正的有效用途,只不过是应用了kts脚本后, 自己就须要编译kotlin内容,因此 默认使用了kotlin编译插件
言归正传,使用这种管理方式后,咱们解决了无代码提示的弊端,再次 利用机器解放生产力
。
可是,咱们没有解决服务端例子中的问题
我想你已经深入意识到了buildSrc机制的本质是啥:
利用Gradle 编译 buildSrc内容,产物供
后续的
该项目的
Gradle编译过程
使用
那么你必定能够想到,buildSrc能够申明自身的依赖!
因而,咱们对经常使用库包进行分析后,选取对象并肯定版本后,便可编写一个Library,
这是最简单的作法,便可在多个Project下,以最小的人力成本管理依赖并知足 一致性需求
Library依赖 Gradle后,能够编写 Gradle-Task内容配置 的过程代码,封装 依赖添加
和 依赖检查
等内容。
举个简单的例子:
object KDeps {
// @JvmStatic
const val ext_junit = "androidx.test.ext:junit:1.1.2"
}
复制代码
public class Deps {
public static String junit = "junit:junit:4.13.0";
public static void applyAll(Project project) {
project.getDependencies().add(
"testImplementation", junit
);
project.getDependencies().add(
"androidTestImplementation",KDeps.ext_junit
);
}
}
复制代码
buildSrc/build.gradle
apply plugin: "kotlin"
buildscript {
ext.kotlin_version = "1.4.21"
repositories {
jcenter()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// implementation 'com.android.tools.build:gradle:4.1.1'
//gradle sdk
gradleApi()
}
}
repositories {
jcenter()
}
复制代码
在app 的build.gradle中,能够这样使用:
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
//略
}
dependencies {
//略
//修改成直接在 afterEvaluate 后调用函数设置
// testImplementation Deps.junit
// androidTestImplementation KDeps.ext_junit
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
afterEvaluate {
Deps.applyAll(project)
}
复制代码
固然,咱们在这个过程当中还可使用各种编程技巧。
此时,咱们已经拥有了无限可能,根据项目的实际需求
,自行拓展吧。