当一个工程愈来愈大,功能愈来愈复杂以后,成员愈来愈多的状况下,如何维护一个巨大的安卓项目呢?php
第一阶段,你们确定都是会把公共模块什么的都抽取出来,封装成aar,以后经过maven的方式引入。java
第二阶段,引入路由以及spi,把项目打散成一个个子module,而后每一个人负责一两个模块之类的,这样就能保证并行开发了。android
第三阶段,当项目臃肿到编译速度愈来愈慢的状况下。这个时候会先抽象一个壳工程,而后把因此的子项模块用aar的方式引入这个壳,以后会把每一个业务放在一个仓库内,这样多个业务之间就不会出现代码冲突之类的问题了。git
这个时候会出现另一些更困扰的问题。github
那么有没有现成的轮子能够解决这些工程化以后会碰到的问题呢?json
Gradle Repo 容我给你们安利个项目,咱们当前项目使用的轮子就是这个。Github传送门app
做者对于这个仓库的描述是这样的。maven
Gradle Repo是基于Gradle写的一个插件,用于管理多个Git仓库,支持方便快捷的切换分支。在根项目中会有一份配置清单repo.xml,用于描述模块来源、工程结构以及依赖关系。gitlab
主要作了三件事情:post
从各个远程仓库clone代码到指定目录路径下。经过Git的exclude而不是submodule。 动态include模块,并模块间的依赖关系,切换至指定分支。
文字描述上可能仍是有些不够清晰哦,咱们经过一张做者的图片去分析这个功能。
而后我本身写了个mock的repo.xml的文件,咱们经过这个xml来简单说下作了什么。
<?xml version='1.0' encoding='UTF-8'?>
<manifest>
<substitute project=":module" targetModule="com.a.b:c"/>
<module name="RouterLib" origin="https://github.com/Leifzhang/Router-Android.git" srcBuild="false" substitute="com.github.leifzhang:routerLib" />
</manifest>
复制代码
这个是我根据项目内生成的一个高度类似的模版。
当项目使用了Gradle Repo调整以后,咱们能够随意的拔插咱们须要的模块,同时把多个模块仓库组合在一块儿同时编译。同时在ci上的则仍是经过implementation依赖的仓库,咱们在开发的时候不会影响到别的业务线的开发,同时在不一样的因为每一个仓库都是独立的gitlab,因此在branch管理上也会有个自然的优点。
其实也不是,那么因为项目散落在不一样的仓库内,因此必然会出现一个问题,如何统一管理项目内的aar版本呢??????
不知道各位有没有注意过前一阵子有个老哥写的文章叫JakeWharton评价个人代码像是在打地鼠?。其实jake大神说的configurations.all就是这里的解决方案了。
那么让我给你们简单的介绍下,configurations.all的做用就是强制拉平项目内的maven aar版本号。若是当项目经过implementation依赖引入了不一样版本的aar的状况下,会以configurations.all内定义的版本为准,忽略掉项目内使用的差别版本。
configurations.all {
resolutionStrategy {
force "com.android.support:appcompat-v7:28.0.0"
}
}
复制代码
上面的代码的意思就是,强制项目内的supportv7版本到28.0.0版本上去。
若是简单的使用configurations,仍是会出现每一个业务模块都须要处理的状况,没法把这个能力收束到一个盒子内,这个时候咱们能够考虑经过一个gradle plugin,自定义一个task的方式,对这个能力进行一次拓展。
首先咱们须要定义一份远端的和branch版本相关的gradle文件,这个文件内能够定义好咱们之前在工程目录下所熟悉的maven仓库的版本。
dep = [
fastjson : "com.alibaba:fastjson:${fastjsonVersion}",
//三方控件
androidSupportV4 : "com.android.support:support-v4:${androidSupportV4Version}",
androidSupportV7 : "com.android.support:appcompat-v7:${androidSupportV7Version}",
androidLifecycle : "android.arch.lifecycle:runtime:${androidLifecycleVersion}",
androidLifecycleCommon : "android.arch.lifecycle:common:${androidLifecycleVersion}",
androidLifecycleCommonJava8 : "android.arch.lifecycle:common-java8:${androidLifecycleVersion}",
androidLifecycleCompiler : "android.arch.lifecycle:compiler:${androidLifecycleVersion}",
androidLifecycleExtensions:"android.arch.lifecycle:extensions:${androidLifecycleVersion}",
recyclerview : "com.android.support:recyclerview-v7:${recyclerviewVersion}",
androidSupportAnnotations: "com.android.support:support-annotations:${androidSupportVersion}"
]
复制代码
而后咱们自定义一个gradle插件,而后生成一个本身的task任务,同步命令被执行的时候,咱们就经过接口调用或者git操做的方式去获取远端的gradle,而后更改项目的gralde configurations.all的方式,去吧项目内的aar版本拉平。
class AATask : DefaultTask() {
@TaskAction
fun apply() {
##伪代码 从远端拉取Dep配置
//强制更换项目内配置
forceConfigVersion(project)
}
fun forceConfigVersion(project: Project) {
project.subprojects {
val depModuleSelectorNotations = mutableListOf<String>()
project.extensions.extraProperties.properties.forEach { key, any ->
if (any!=null && key!=null&&key.endsWith("dep")){
if (any is Map<*, *>){
collectDepModuleVersionSelectorNotations(depModuleSelectorNotations, any)
}
}
}
it.configurations.all { configuration ->
configuration.resolutionStrategy.force(depModuleSelectorNotations)
}
}
}
复制代码
具体详细的内容涉及到公司代码就不和你们详细的展开了,思路核心就是一切三方库的版本以远端的branch做为标准。
本文只是一篇科普文章,并不涉及到任何代码分析,若是有什么得罪的地方,你也打不到我。